<commit_before>//
//  Copyright (c) 2016 Terry Seyler
//
//  Distributed under the MIT License
//  See accompanying file LICENSE.md
//

#include <ostream>
#include <istream>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <core/client/proto_tcp_text_client.hpp>
#include <core/data/proto_net_error_data.hpp>

namespace proto_net
{
    namespace client
    {
         proto_tcp_text_client*
         proto_tcp_text_client::proto_tcp_text_client_cast(proto_service_ptr ps_ptr)
        {
            return dynamic_cast<proto_tcp_text_client*>(ps_ptr.get());
        }

        proto_tcp_text_client::proto_tcp_text_client(const std::string& address,
                                           unsigned short port_num /* = 80*/,
                                           proto_net_pipeline& ps_pipeline/* = empty_pipeline_inst*/,
                                           size_t buffer_size /*= 4096*/)
                : proto_tcp_client(address, port_num, ps_pipeline, buffer_size)
        {}

        proto_tcp_text_client::~proto_tcp_text_client()
        {}

        proto_tcp_text_client::proto_tcp_text_client(proto_net_service_ptr ps_service, const std::string& address,
                                                     unsigned short port_num /* = 80*/,
                                                     proto_net_pipeline& ps_pipeline/* = empty_pipeline_inst*/,
                                                     size_t buffer_size /*= 4096*/)
                : proto_tcp_client(ps_service, address, port_num, ps_pipeline, buffer_size)
        {}

        void
        proto_tcp_text_client::ps_async_read(void)
        {
            boost::asio::async_read_until(socket_, read_stream_buffer_, '\0',
                                          boost::bind(&proto_tcp_text_client::ps_handle_read, this,
                                                      boost::asio::placeholders::error,
                                                      boost::asio::placeholders::bytes_transferred));
        }

        void
        proto_tcp_text_client::ps_async_write(proto_net_in_data& data_in)
        {

            if (data_in.data() && data_in.data_size() && data_in.data_type() == data_text) //guard against empty data getting put into the pipe in
            {
                if (ps_write_complete(max_wait_msec_)) // write is complete
                {
                    ps_pipeline_.ps_pipe_in(data_in); // just prior to the write, execute the pipe_in

                    char *data = data_in.data();
                    size_t data_size = data_in.data_size();
                    if (data && data_size)
                    {
                        boost::asio::async_write(socket_, boost::asio::buffer(data, data_size),
                                                 boost::bind(&proto_tcp_text_client::ps_handle_write, this,
                                                             boost::asio::placeholders::error,
                                                             boost::asio::placeholders::bytes_transferred));
                        write_complete_ = false;
                    }
                    else
                        ps_async_read(); // just go back to reading
                }
                else
                    ps_async_read(); // just go back to reading
            }
            else
                ps_async_read(); // just go back to reading
        }

        void
        proto_tcp_text_client::ps_handle_read(const boost::system::error_code& error, size_t bytes_transferred)
        {
            if (!error)
            {
                std::istream is(&read_stream_buffer_);
                delete [] buffer_;
                is.get(buffer_, buffer_size_, '\0');

                // handle a ps_read here
                std::string response(buffer_);
                proto_net_data res_data(response);
                std::string request;
                proto_net_data req_data(request);
                if (res_data.data_size())
                {
                    ps_pipeline_.ps_pipeline(res_data, req_data); // response and request are reversed here
                    ps_pipeline_.ps_pipe_out(res_data); // post read, execute the pipe_out for the client
                }
               // read_stream_buffer_.consume(read_stream_buffer_.size());
                read_stream_buffer_.consume(bytes_transferred);
                read_stream_buffer_.prepare(buffer_size_);
                write_complete_ = true;

                ps_async_read(); // done go back to reading
            }
            else
            {
                proto_net_error_data err_data(ec_read_error);
                if (ps_pipeline_.ps_pipe_error(err_data))
                {
                    //delete this; // for now
                }
                else
                    ps_async_read(); // done go back to reading;
            }

        }

        void
        proto_tcp_text_client::ps_handle_write(const boost::system::error_code &error, size_t bytes_transferred)
        {
            if (!error)
            {
                // handle a post write here
                ps_async_read(); // just go back to reading
            }
            else
                delete this;
        }

    }
}<commit_msg>Removed bad delete in read handler<commit_after>//
//  Copyright (c) 2016 Terry Seyler
//
//  Distributed under the MIT License
//  See accompanying file LICENSE.md
//

#include <ostream>
#include <istream>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <core/client/proto_tcp_text_client.hpp>
#include <core/data/proto_net_error_data.hpp>

namespace proto_net
{
    namespace client
    {
         proto_tcp_text_client*
         proto_tcp_text_client::proto_tcp_text_client_cast(proto_service_ptr ps_ptr)
        {
            return dynamic_cast<proto_tcp_text_client*>(ps_ptr.get());
        }

        proto_tcp_text_client::proto_tcp_text_client(const std::string& address,
                                           unsigned short port_num /* = 80*/,
                                           proto_net_pipeline& ps_pipeline/* = empty_pipeline_inst*/,
                                           size_t buffer_size /*= 4096*/)
                : proto_tcp_client(address, port_num, ps_pipeline, buffer_size)
        {}

        proto_tcp_text_client::~proto_tcp_text_client()
        {}

        proto_tcp_text_client::proto_tcp_text_client(proto_net_service_ptr ps_service, const std::string& address,
                                                     unsigned short port_num /* = 80*/,
                                                     proto_net_pipeline& ps_pipeline/* = empty_pipeline_inst*/,
                                                     size_t buffer_size /*= 4096*/)
                : proto_tcp_client(ps_service, address, port_num, ps_pipeline, buffer_size)
        {}

        void
        proto_tcp_text_client::ps_async_read(void)
        {
            boost::asio::async_read_until(socket_, read_stream_buffer_, '\0',
                                          boost::bind(&proto_tcp_text_client::ps_handle_read, this,
                                                      boost::asio::placeholders::error,
                                                      boost::asio::placeholders::bytes_transferred));
        }

        void
        proto_tcp_text_client::ps_async_write(proto_net_in_data& data_in)
        {

            if (data_in.data() && data_in.data_size() && data_in.data_type() == data_text) //guard against empty data getting put into the pipe in
            {
                if (ps_write_complete(max_wait_msec_)) // write is complete
                {
                    ps_pipeline_.ps_pipe_in(data_in); // just prior to the write, execute the pipe_in

                    char *data = data_in.data();
                    size_t data_size = data_in.data_size();
                    if (data && data_size)
                    {
                        boost::asio::async_write(socket_, boost::asio::buffer(data, data_size),
                                                 boost::bind(&proto_tcp_text_client::ps_handle_write, this,
                                                             boost::asio::placeholders::error,
                                                             boost::asio::placeholders::bytes_transferred));
                        write_complete_ = false;
                    }
                    else
                        ps_async_read(); // just go back to reading
                }
                else
                    ps_async_read(); // just go back to reading
            }
            else
                ps_async_read(); // just go back to reading
        }

        void
        proto_tcp_text_client::ps_handle_read(const boost::system::error_code& error, size_t bytes_transferred)
        {
            if (!error)
            {
                std::istream is(&read_stream_buffer_);
                memset(buffer_, 0, buffer_size_);
                is.get(buffer_, buffer_size_, '\0');

                // handle a ps_read here
                std::string response(buffer_);
                proto_net_data res_data(response);
                std::string request;
                proto_net_data req_data(request);
                if (res_data.data_size())
                {
                    ps_pipeline_.ps_pipeline(res_data, req_data); // response and request are reversed here
                    ps_pipeline_.ps_pipe_out(res_data); // post read, execute the pipe_out for the client
                }
               // read_stream_buffer_.consume(read_stream_buffer_.size());
                read_stream_buffer_.consume(bytes_transferred);
                read_stream_buffer_.prepare(buffer_size_);
                write_complete_ = true;

                ps_async_read(); // done go back to reading
            }
            else
            {
                proto_net_error_data err_data(ec_read_error);
                if (ps_pipeline_.ps_pipe_error(err_data))
                {
                    //delete this; // for now
                }
                else
                    ps_async_read(); // done go back to reading;
            }

        }

        void
        proto_tcp_text_client::ps_handle_write(const boost::system::error_code &error, size_t bytes_transferred)
        {
            if (!error)
            {
                // handle a post write here
                ps_async_read(); // just go back to reading
            }
            else
                delete this;
        }

    }
}<|endoftext|>


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

#include "MappedLLVMValue.hpp"

#include "seec/Util/ModuleIndex.hpp"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Value.h"

namespace seec {

namespace cm {

llvm::Value const *
getMappedValueFromMD(llvm::MDNode const *ValueMap,
                     ModuleIndex const &ModIndex)
{
  if (!ValueMap || ValueMap->getNumOperands() == 0) {
    return nullptr;
  }

  auto Type = llvm::dyn_cast<llvm::MDString>(ValueMap->getOperand(0u));
  auto TypeStr = Type->getString();

  if (TypeStr.equals("instruction")) {
    assert(ValueMap->getNumOperands() == 3);
    auto Func = llvm::dyn_cast<llvm::Function>(ValueMap->getOperand(1u));
    auto Idx = llvm::dyn_cast<llvm::ConstantInt>(ValueMap->getOperand(2u));
    assert(Func && Idx);
    auto FuncIndex = ModIndex.getFunctionIndex(Func);
    assert(FuncIndex);
    auto IdxValue = static_cast<uint32_t>(Idx->getZExtValue());
    return FuncIndex->getInstruction(IdxValue);
  }
  else if (TypeStr.equals("value")) {
    assert(ValueMap->getNumOperands() == 2);
    return ValueMap->getOperand(1u);
  }
  else if (TypeStr.equals("argument")) {
    assert(ValueMap->getNumOperands() == 3);
    auto Func = llvm::dyn_cast<llvm::Function>(ValueMap->getOperand(1u));
    auto Idx = llvm::dyn_cast<llvm::ConstantInt>(ValueMap->getOperand(2u));
    assert(Func && Idx);
    auto FuncIndex = ModIndex.getFunctionIndex(Func);
    assert(FuncIndex);
    auto IdxValue = static_cast<uint32_t>(Idx->getZExtValue());
    return FuncIndex->getArgument(IdxValue);
  }
  else {
    llvm_unreachable("Encountered unknown value type.");
    return nullptr;
  }
}

} // namespace cm (in seec)

} // namespace seec
<commit_msg>Ignore mappings for null Functions (rather than asserting).<commit_after>//===- lib/Clang/MappedLLVMValue.cpp --------------------------------------===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#include "MappedLLVMValue.hpp"

#include "seec/Util/ModuleIndex.hpp"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Value.h"

namespace seec {

namespace cm {

llvm::Value const *
getMappedValueFromMD(llvm::MDNode const *ValueMap,
                     ModuleIndex const &ModIndex)
{
  if (!ValueMap || ValueMap->getNumOperands() == 0) {
    return nullptr;
  }

  auto Type = llvm::dyn_cast<llvm::MDString>(ValueMap->getOperand(0u));
  auto TypeStr = Type->getString();

  if (TypeStr.equals("instruction")) {
    assert(ValueMap->getNumOperands() == 3);

    auto FuncVal = ValueMap->getOperand(1u);
    if (!FuncVal)
      return nullptr;

    auto Func = llvm::dyn_cast<llvm::Function>(ValueMap->getOperand(1u));
    auto Idx = llvm::dyn_cast<llvm::ConstantInt>(ValueMap->getOperand(2u));
    assert(Idx);

    auto FuncIndex = ModIndex.getFunctionIndex(Func);
    assert(FuncIndex);

    auto IdxValue = static_cast<uint32_t>(Idx->getZExtValue());
    return FuncIndex->getInstruction(IdxValue);
  }
  else if (TypeStr.equals("value")) {
    assert(ValueMap->getNumOperands() == 2);
    return ValueMap->getOperand(1u);
  }
  else if (TypeStr.equals("argument")) {
    assert(ValueMap->getNumOperands() == 3);
    auto Func = llvm::dyn_cast<llvm::Function>(ValueMap->getOperand(1u));
    auto Idx = llvm::dyn_cast<llvm::ConstantInt>(ValueMap->getOperand(2u));
    assert(Func && Idx);
    auto FuncIndex = ModIndex.getFunctionIndex(Func);
    assert(FuncIndex);
    auto IdxValue = static_cast<uint32_t>(Idx->getZExtValue());
    return FuncIndex->getArgument(IdxValue);
  }
  else {
    llvm_unreachable("Encountered unknown value type.");
    return nullptr;
  }
}

} // namespace cm (in seec)

} // namespace seec
<|endoftext|>


<commit_before>//=-- InstrProf.cpp - Instrumented profiling format support -----------------=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains support for clang's instrumentation based PGO and
// coverage.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"

using namespace llvm;

namespace {
class InstrProfErrorCategoryType : public std::error_category {
  const char *name() const LLVM_NOEXCEPT override { return "llvm.instrprof"; }
  std::string message(int IE) const override {
    instrprof_error E = static_cast<instrprof_error>(IE);
    switch (E) {
    case instrprof_error::success:
      return "Success";
    case instrprof_error::eof:
      return "End of File";
    case instrprof_error::unrecognized_format:
      return "Unrecognized instrumentation profile encoding format";
    case instrprof_error::bad_magic:
      return "Invalid instrumentation profile data (bad magic)";
    case instrprof_error::bad_header:
      return "Invalid instrumentation profile data (file header is corrupt)";
    case instrprof_error::unsupported_version:
      return "Unsupported instrumentation profile format version";
    case instrprof_error::unsupported_hash_type:
      return "Unsupported instrumentation profile hash type";
    case instrprof_error::too_large:
      return "Too much profile data";
    case instrprof_error::truncated:
      return "Truncated profile data";
    case instrprof_error::malformed:
      return "Malformed instrumentation profile data";
    case instrprof_error::unknown_function:
      return "No profile data available for function";
    case instrprof_error::hash_mismatch:
      return "Function control flow change detected (hash mismatch)";
    case instrprof_error::count_mismatch:
      return "Function basic block count change detected (counter mismatch)";
    case instrprof_error::counter_overflow:
      return "Counter overflow";
    case instrprof_error::value_site_count_mismatch:
      return "Function value site count change detected (counter mismatch)";
    }
    llvm_unreachable("A value of instrprof_error has no message.");
  }
};
}

static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory;

const std::error_category &llvm::instrprof_category() {
  return *ErrorCategory;
}

namespace llvm {

std::string getPGOFuncName(StringRef RawFuncName,
                           GlobalValue::LinkageTypes Linkage,
                           StringRef FileName) {

  // Function names may be prefixed with a binary '1' to indicate
  // that the backend should not modify the symbols due to any platform
  // naming convention. Do not include that '1' in the PGO profile name.
  if (RawFuncName[0] == '\1')
    RawFuncName = RawFuncName.substr(1);

  std::string FuncName = RawFuncName;
  if (llvm::GlobalValue::isLocalLinkage(Linkage)) {
    // For local symbols, prepend the main file name to distinguish them.
    // Do not include the full path in the file name since there's no guarantee
    // that it will stay the same, e.g., if the files are checked out from
    // version control in different locations.
    if (FileName.empty())
      FuncName = FuncName.insert(0, "<unknown>:");
    else
      FuncName = FuncName.insert(0, FileName.str() + ":");
  }
  return FuncName;
}

std::string getPGOFuncName(const Function &F) {
  return getPGOFuncName(F.getName(), F.getLinkage(), F.getParent()->getName());
}

GlobalVariable *createPGOFuncNameVar(Module &M,
                                     GlobalValue::LinkageTypes Linkage,
                                     StringRef FuncName) {

  // We generally want to match the function's linkage, but available_externally
  // and extern_weak both have the wrong semantics, and anything that doesn't
  // need to link across compilation units doesn't need to be visible at all.
  if (Linkage == GlobalValue::ExternalWeakLinkage)
    Linkage = GlobalValue::LinkOnceAnyLinkage;
  else if (Linkage == GlobalValue::AvailableExternallyLinkage)
    Linkage = GlobalValue::LinkOnceODRLinkage;
  else if (Linkage == GlobalValue::InternalLinkage ||
           Linkage == GlobalValue::ExternalLinkage)
    Linkage = GlobalValue::PrivateLinkage;

  auto *Value = ConstantDataArray::getString(M.getContext(), FuncName, false);
  auto FuncNameVar =
      new GlobalVariable(M, Value->getType(), true, Linkage, Value,
                         Twine(getInstrProfNameVarPrefix()) + FuncName);

  // Hide the symbol so that we correctly get a copy for each executable.
  if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
    FuncNameVar->setVisibility(GlobalValue::HiddenVisibility);

  return FuncNameVar;
}

GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName) {
  return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), FuncName);
}

uint64_t StringToHash(uint32_t ValueKind, uint64_t Value) {
  switch (ValueKind) {
  case IPVK_IndirectCallTarget:
    return IndexedInstrProf::ComputeHash(IndexedInstrProf::HashType,
                                         (const char *)Value);
    break;
  default:
    llvm_unreachable("value kind not handled !");
  }
  return Value;
}

void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
                                    InstrProfRecord::ValueMapType *VMap) {
  Record.reserveSites(Kind, NumValueSites);

  InstrProfValueData *ValueData = this->getValueData();
  for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) {
    uint8_t ValueDataCount = this->SiteCountArray[VSite];
    Record.addValueData(Kind, VSite, ValueData, ValueDataCount, VMap);
    ValueData += ValueDataCount;
  }
}

void ValueProfRecord::serializeFrom(const InstrProfRecord &Record,
                                    uint32_t ValueKind,
                                    uint32_t NumValueSites) {
  Kind = ValueKind;
  this->NumValueSites = NumValueSites;
  InstrProfValueData *DstVD = getValueData();
  for (uint32_t S = 0; S < NumValueSites; S++) {
    uint32_t ND = Record.getNumValueDataForSite(ValueKind, S);
    SiteCountArray[S] = ND;
    Record.getValueForSite(DstVD, ValueKind, S, StringToHash);
    DstVD += ND;
  }
}

template <class T>
static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) {
  using namespace support;
  if (Orig == little)
    return endian::readNext<T, little, unaligned>(D);
  else
    return endian::readNext<T, big, unaligned>(D);
}

// For writing/serializing,  Old is the host endianness, and  New is
// byte order intended on disk. For Reading/deserialization, Old
// is the on-disk source endianness, and New is the host endianness.
void ValueProfRecord::swapBytes(support::endianness Old,
                                support::endianness New) {
  using namespace support;
  if (Old == New)
    return;

  if (getHostEndianness() != Old) {
    sys::swapByteOrder<uint32_t>(NumValueSites);
    sys::swapByteOrder<uint32_t>(Kind);
  }
  uint32_t ND = getNumValueData();
  InstrProfValueData *VD = getValueData();

  // No need to swap byte array: SiteCountArrray.
  for (uint32_t I = 0; I < ND; I++) {
    sys::swapByteOrder<uint64_t>(VD[I].Value);
    sys::swapByteOrder<uint64_t>(VD[I].Count);
  }
  if (getHostEndianness() == Old) {
    sys::swapByteOrder<uint32_t>(NumValueSites);
    sys::swapByteOrder<uint32_t>(Kind);
  }
}

uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
  uint32_t TotalSize = sizeof(ValueProfData);
  uint32_t NumValueKinds = Record.getNumValueKinds();
  if (NumValueKinds == 0)
    return TotalSize;

  for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
    uint32_t NumValueSites = Record.getNumValueSites(Kind);
    if (!NumValueSites)
      continue;
    TotalSize +=
        getValueProfRecordSize(NumValueSites, Record.getNumValueData(Kind));
  }
  return TotalSize;
}

void ValueProfData::deserializeTo(InstrProfRecord &Record,
                                  InstrProfRecord::ValueMapType *VMap) {
  if (NumValueKinds == 0)
    return;

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    VR->deserializeTo(Record, VMap);
    VR = VR->getNext();
  }
}

static std::unique_ptr<ValueProfData> AllocValueProfData(uint32_t TotalSize) {
  return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize))
                                            ValueProfData());
}

std::unique_ptr<ValueProfData>
ValueProfData::serializeFrom(const InstrProfRecord &Record) {
  uint32_t TotalSize = getSize(Record);

  std::unique_ptr<ValueProfData> VPD = AllocValueProfData(TotalSize);

  VPD->TotalSize = TotalSize;
  VPD->NumValueKinds = Record.getNumValueKinds();
  ValueProfRecord *VR = VPD->getFirstValueProfRecord();
  for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
    uint32_t NumValueSites = Record.getNumValueSites(Kind);
    if (!NumValueSites)
      continue;
    VR->serializeFrom(Record, Kind, NumValueSites);
    VR = VR->getNext();
  }
  return VPD;
}

ErrorOr<std::unique_ptr<ValueProfData>>
ValueProfData::getValueProfData(const unsigned char *D,
                                const unsigned char *const BufferEnd,
                                support::endianness Endianness) {
  using namespace support;
  if (D + sizeof(ValueProfData) > BufferEnd)
    return instrprof_error::truncated;

  const unsigned char *Header = D;
  uint32_t TotalSize = swapToHostOrder<uint32_t>(Header, Endianness);
  uint32_t NumValueKinds = swapToHostOrder<uint32_t>(Header, Endianness);

  if (D + TotalSize > BufferEnd)
    return instrprof_error::too_large;
  if (NumValueKinds > IPVK_Last + 1)
    return instrprof_error::malformed;
  // Total size needs to be mulltiple of quadword size.
  if (TotalSize % sizeof(uint64_t))
    return instrprof_error::malformed;

  std::unique_ptr<ValueProfData> VPD = AllocValueProfData(TotalSize);

  memcpy(VPD.get(), D, TotalSize);
  // Byte swap.
  VPD->swapBytesToHost(Endianness);

  // Data integrety check:
  ValueProfRecord *VR = VPD->getFirstValueProfRecord();
  for (uint32_t K = 0; K < VPD->NumValueKinds; K++) {
    if (VR->Kind > IPVK_Last)
      return instrprof_error::malformed;
    VR = VR->getNext();
    if ((char *)VR - (char *)VPD.get() > (ptrdiff_t)TotalSize)
      return instrprof_error::malformed;
  }

  return std::move(VPD);
}

void ValueProfData::swapBytesToHost(support::endianness Endianness) {
  using namespace support;
  if (Endianness == getHostEndianness())
    return;

  sys::swapByteOrder<uint32_t>(TotalSize);
  sys::swapByteOrder<uint32_t>(NumValueKinds);

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    VR->swapBytes(Endianness, getHostEndianness());
    VR = VR->getNext();
  }
}

void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
  using namespace support;
  if (Endianness == getHostEndianness())
    return;

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    ValueProfRecord *NVR = VR->getNext();
    VR->swapBytes(getHostEndianness(), Endianness);
    VR = NVR;
  }
  sys::swapByteOrder<uint32_t>(TotalSize);
  sys::swapByteOrder<uint32_t>(NumValueKinds);
}

ValueProfRecord *ValueProfData::getFirstValueProfRecord() {
  return reinterpret_cast<ValueProfRecord *>((char *)this +
                                             sizeof(ValueProfData));
}

uint32_t ValueProfRecord::getNumValueData() const {
  uint32_t NumValueData = 0;
  for (uint32_t I = 0; I < NumValueSites; I++)
    NumValueData += SiteCountArray[I];
  return NumValueData;
}

ValueProfRecord *ValueProfRecord::getNext() {
  return reinterpret_cast<ValueProfRecord *>((char *)this + getSize());
}

InstrProfValueData *ValueProfRecord::getValueData() {
  return reinterpret_cast<InstrProfValueData *>(
      (char *)this + getValueProfRecordHeaderSize(NumValueSites));
}
}
<commit_msg>Fix function naming (NFC)<commit_after>//=-- InstrProf.cpp - Instrumented profiling format support -----------------=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains support for clang's instrumentation based PGO and
// coverage.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"

using namespace llvm;

namespace {
class InstrProfErrorCategoryType : public std::error_category {
  const char *name() const LLVM_NOEXCEPT override { return "llvm.instrprof"; }
  std::string message(int IE) const override {
    instrprof_error E = static_cast<instrprof_error>(IE);
    switch (E) {
    case instrprof_error::success:
      return "Success";
    case instrprof_error::eof:
      return "End of File";
    case instrprof_error::unrecognized_format:
      return "Unrecognized instrumentation profile encoding format";
    case instrprof_error::bad_magic:
      return "Invalid instrumentation profile data (bad magic)";
    case instrprof_error::bad_header:
      return "Invalid instrumentation profile data (file header is corrupt)";
    case instrprof_error::unsupported_version:
      return "Unsupported instrumentation profile format version";
    case instrprof_error::unsupported_hash_type:
      return "Unsupported instrumentation profile hash type";
    case instrprof_error::too_large:
      return "Too much profile data";
    case instrprof_error::truncated:
      return "Truncated profile data";
    case instrprof_error::malformed:
      return "Malformed instrumentation profile data";
    case instrprof_error::unknown_function:
      return "No profile data available for function";
    case instrprof_error::hash_mismatch:
      return "Function control flow change detected (hash mismatch)";
    case instrprof_error::count_mismatch:
      return "Function basic block count change detected (counter mismatch)";
    case instrprof_error::counter_overflow:
      return "Counter overflow";
    case instrprof_error::value_site_count_mismatch:
      return "Function value site count change detected (counter mismatch)";
    }
    llvm_unreachable("A value of instrprof_error has no message.");
  }
};
}

static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory;

const std::error_category &llvm::instrprof_category() {
  return *ErrorCategory;
}

namespace llvm {

std::string getPGOFuncName(StringRef RawFuncName,
                           GlobalValue::LinkageTypes Linkage,
                           StringRef FileName) {

  // Function names may be prefixed with a binary '1' to indicate
  // that the backend should not modify the symbols due to any platform
  // naming convention. Do not include that '1' in the PGO profile name.
  if (RawFuncName[0] == '\1')
    RawFuncName = RawFuncName.substr(1);

  std::string FuncName = RawFuncName;
  if (llvm::GlobalValue::isLocalLinkage(Linkage)) {
    // For local symbols, prepend the main file name to distinguish them.
    // Do not include the full path in the file name since there's no guarantee
    // that it will stay the same, e.g., if the files are checked out from
    // version control in different locations.
    if (FileName.empty())
      FuncName = FuncName.insert(0, "<unknown>:");
    else
      FuncName = FuncName.insert(0, FileName.str() + ":");
  }
  return FuncName;
}

std::string getPGOFuncName(const Function &F) {
  return getPGOFuncName(F.getName(), F.getLinkage(), F.getParent()->getName());
}

GlobalVariable *createPGOFuncNameVar(Module &M,
                                     GlobalValue::LinkageTypes Linkage,
                                     StringRef FuncName) {

  // We generally want to match the function's linkage, but available_externally
  // and extern_weak both have the wrong semantics, and anything that doesn't
  // need to link across compilation units doesn't need to be visible at all.
  if (Linkage == GlobalValue::ExternalWeakLinkage)
    Linkage = GlobalValue::LinkOnceAnyLinkage;
  else if (Linkage == GlobalValue::AvailableExternallyLinkage)
    Linkage = GlobalValue::LinkOnceODRLinkage;
  else if (Linkage == GlobalValue::InternalLinkage ||
           Linkage == GlobalValue::ExternalLinkage)
    Linkage = GlobalValue::PrivateLinkage;

  auto *Value = ConstantDataArray::getString(M.getContext(), FuncName, false);
  auto FuncNameVar =
      new GlobalVariable(M, Value->getType(), true, Linkage, Value,
                         Twine(getInstrProfNameVarPrefix()) + FuncName);

  // Hide the symbol so that we correctly get a copy for each executable.
  if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
    FuncNameVar->setVisibility(GlobalValue::HiddenVisibility);

  return FuncNameVar;
}

GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName) {
  return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), FuncName);
}

uint64_t stringToHash(uint32_t ValueKind, uint64_t Value) {
  switch (ValueKind) {
  case IPVK_IndirectCallTarget:
    return IndexedInstrProf::ComputeHash(IndexedInstrProf::HashType,
                                         (const char *)Value);
    break;
  default:
    llvm_unreachable("value kind not handled !");
  }
  return Value;
}

void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
                                    InstrProfRecord::ValueMapType *VMap) {
  Record.reserveSites(Kind, NumValueSites);

  InstrProfValueData *ValueData = this->getValueData();
  for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) {
    uint8_t ValueDataCount = this->SiteCountArray[VSite];
    Record.addValueData(Kind, VSite, ValueData, ValueDataCount, VMap);
    ValueData += ValueDataCount;
  }
}

void ValueProfRecord::serializeFrom(const InstrProfRecord &Record,
                                    uint32_t ValueKind,
                                    uint32_t NumValueSites) {
  Kind = ValueKind;
  this->NumValueSites = NumValueSites;
  InstrProfValueData *DstVD = getValueData();
  for (uint32_t S = 0; S < NumValueSites; S++) {
    uint32_t ND = Record.getNumValueDataForSite(ValueKind, S);
    SiteCountArray[S] = ND;
    Record.getValueForSite(DstVD, ValueKind, S, stringToHash);
    DstVD += ND;
  }
}

template <class T>
static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) {
  using namespace support;
  if (Orig == little)
    return endian::readNext<T, little, unaligned>(D);
  else
    return endian::readNext<T, big, unaligned>(D);
}

// For writing/serializing,  Old is the host endianness, and  New is
// byte order intended on disk. For Reading/deserialization, Old
// is the on-disk source endianness, and New is the host endianness.
void ValueProfRecord::swapBytes(support::endianness Old,
                                support::endianness New) {
  using namespace support;
  if (Old == New)
    return;

  if (getHostEndianness() != Old) {
    sys::swapByteOrder<uint32_t>(NumValueSites);
    sys::swapByteOrder<uint32_t>(Kind);
  }
  uint32_t ND = getNumValueData();
  InstrProfValueData *VD = getValueData();

  // No need to swap byte array: SiteCountArrray.
  for (uint32_t I = 0; I < ND; I++) {
    sys::swapByteOrder<uint64_t>(VD[I].Value);
    sys::swapByteOrder<uint64_t>(VD[I].Count);
  }
  if (getHostEndianness() == Old) {
    sys::swapByteOrder<uint32_t>(NumValueSites);
    sys::swapByteOrder<uint32_t>(Kind);
  }
}

uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
  uint32_t TotalSize = sizeof(ValueProfData);
  uint32_t NumValueKinds = Record.getNumValueKinds();
  if (NumValueKinds == 0)
    return TotalSize;

  for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
    uint32_t NumValueSites = Record.getNumValueSites(Kind);
    if (!NumValueSites)
      continue;
    TotalSize +=
        getValueProfRecordSize(NumValueSites, Record.getNumValueData(Kind));
  }
  return TotalSize;
}

void ValueProfData::deserializeTo(InstrProfRecord &Record,
                                  InstrProfRecord::ValueMapType *VMap) {
  if (NumValueKinds == 0)
    return;

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    VR->deserializeTo(Record, VMap);
    VR = VR->getNext();
  }
}

static std::unique_ptr<ValueProfData> AllocValueProfData(uint32_t TotalSize) {
  return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize))
                                            ValueProfData());
}

std::unique_ptr<ValueProfData>
ValueProfData::serializeFrom(const InstrProfRecord &Record) {
  uint32_t TotalSize = getSize(Record);

  std::unique_ptr<ValueProfData> VPD = AllocValueProfData(TotalSize);

  VPD->TotalSize = TotalSize;
  VPD->NumValueKinds = Record.getNumValueKinds();
  ValueProfRecord *VR = VPD->getFirstValueProfRecord();
  for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
    uint32_t NumValueSites = Record.getNumValueSites(Kind);
    if (!NumValueSites)
      continue;
    VR->serializeFrom(Record, Kind, NumValueSites);
    VR = VR->getNext();
  }
  return VPD;
}

ErrorOr<std::unique_ptr<ValueProfData>>
ValueProfData::getValueProfData(const unsigned char *D,
                                const unsigned char *const BufferEnd,
                                support::endianness Endianness) {
  using namespace support;
  if (D + sizeof(ValueProfData) > BufferEnd)
    return instrprof_error::truncated;

  const unsigned char *Header = D;
  uint32_t TotalSize = swapToHostOrder<uint32_t>(Header, Endianness);
  uint32_t NumValueKinds = swapToHostOrder<uint32_t>(Header, Endianness);

  if (D + TotalSize > BufferEnd)
    return instrprof_error::too_large;
  if (NumValueKinds > IPVK_Last + 1)
    return instrprof_error::malformed;
  // Total size needs to be mulltiple of quadword size.
  if (TotalSize % sizeof(uint64_t))
    return instrprof_error::malformed;

  std::unique_ptr<ValueProfData> VPD = AllocValueProfData(TotalSize);

  memcpy(VPD.get(), D, TotalSize);
  // Byte swap.
  VPD->swapBytesToHost(Endianness);

  // Data integrety check:
  ValueProfRecord *VR = VPD->getFirstValueProfRecord();
  for (uint32_t K = 0; K < VPD->NumValueKinds; K++) {
    if (VR->Kind > IPVK_Last)
      return instrprof_error::malformed;
    VR = VR->getNext();
    if ((char *)VR - (char *)VPD.get() > (ptrdiff_t)TotalSize)
      return instrprof_error::malformed;
  }

  return std::move(VPD);
}

void ValueProfData::swapBytesToHost(support::endianness Endianness) {
  using namespace support;
  if (Endianness == getHostEndianness())
    return;

  sys::swapByteOrder<uint32_t>(TotalSize);
  sys::swapByteOrder<uint32_t>(NumValueKinds);

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    VR->swapBytes(Endianness, getHostEndianness());
    VR = VR->getNext();
  }
}

void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
  using namespace support;
  if (Endianness == getHostEndianness())
    return;

  ValueProfRecord *VR = getFirstValueProfRecord();
  for (uint32_t K = 0; K < NumValueKinds; K++) {
    ValueProfRecord *NVR = VR->getNext();
    VR->swapBytes(getHostEndianness(), Endianness);
    VR = NVR;
  }
  sys::swapByteOrder<uint32_t>(TotalSize);
  sys::swapByteOrder<uint32_t>(NumValueKinds);
}

ValueProfRecord *ValueProfData::getFirstValueProfRecord() {
  return reinterpret_cast<ValueProfRecord *>((char *)this +
                                             sizeof(ValueProfData));
}

uint32_t ValueProfRecord::getNumValueData() const {
  uint32_t NumValueData = 0;
  for (uint32_t I = 0; I < NumValueSites; I++)
    NumValueData += SiteCountArray[I];
  return NumValueData;
}

ValueProfRecord *ValueProfRecord::getNext() {
  return reinterpret_cast<ValueProfRecord *>((char *)this + getSize());
}

InstrProfValueData *ValueProfRecord::getValueData() {
  return reinterpret_cast<InstrProfValueData *>(
      (char *)this + getValueProfRecordHeaderSize(NumValueSites));
}
}
<|endoftext|>


<commit_before>//===- Support/FileUtilities.cpp - File System Utilities ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a family of utility functions which are useful for doing
// various things with files.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/FileUtilities.h"
#include "llvm/System/Path.h"
#include "llvm/System/MappedFile.h"
#include "llvm/ADT/StringExtras.h"
#include <cstring>
#include <cctype>
using namespace llvm;

static bool isSignedChar(char C) {
  if (C == '+' || C == '-')
    return true;
  else
    return false;
}

static bool isExpoentChar(char C) {
  switch (C) {
  case 'D':  // Strange exponential notation.
  case 'd':  // Strange exponential notation.
  case 'e':
  case 'E': return true;
  default: return false;
  }
}

static bool isNumberChar(char C) {
  switch (C) {
  case '0': case '1': case '2': case '3': case '4':
  case '5': case '6': case '7': case '8': case '9':
  case '.': return true;
  default: return isSignedChar(C) || isExpoentChar(C);
  }
}

static char *BackupNumber(char *Pos, char *FirstChar) {
  // If we didn't stop in the middle of a number, don't backup.
  if (!isNumberChar(*Pos)) return Pos;

  // Otherwise, return to the start of the number.
  while (Pos > FirstChar && isNumberChar(Pos[-1])) {
    --Pos;
    if (Pos > FirstChar && isSignedChar(Pos[0]) && !isExpoentChar(Pos[-1]))
      break;
  }
  return Pos;
}

/// CompareNumbers - compare two numbers, returning true if they are different.
static bool CompareNumbers(char *&F1P, char *&F2P, char *F1End, char *F2End,
                           double AbsTolerance, double RelTolerance,
                           std::string *ErrorMsg) {
  char *F1NumEnd, *F2NumEnd;
  double V1 = 0.0, V2 = 0.0;

  // If one of the positions is at a space and the other isn't, chomp up 'til
  // the end of the space.
  while (isspace(*F1P) && F1P != F1End)
    ++F1P;
  while (isspace(*F2P) && F2P != F2End)
    ++F2P;

  // If we stop on numbers, compare their difference.  Note that some ugliness
  // is built into this to permit support for numbers that use "D" or "d" as
  // their exponential marker, e.g. "1.234D45".  This occurs in 200.sixtrack in
  // spec2k.
  if (isNumberChar(*F1P) && isNumberChar(*F2P)) {
    bool isDNotation;
    do {
      isDNotation = false;
      V1 = strtod(F1P, &F1NumEnd);
      V2 = strtod(F2P, &F2NumEnd);

      if (*F1NumEnd == 'D' || *F1NumEnd == 'd') {
        *F1NumEnd = 'e';  // Strange exponential notation!
        isDNotation = true;
      }
      if (*F2NumEnd == 'D' || *F2NumEnd == 'd') {
        *F2NumEnd = 'e';  // Strange exponential notation!
        isDNotation = true;
      }
    } while (isDNotation);
  } else {
    // Otherwise, the diff failed.
    F1NumEnd = F1P;
    F2NumEnd = F2P;
  }

  if (F1NumEnd == F1P || F2NumEnd == F2P) {
    if (ErrorMsg) {
      *ErrorMsg = "FP Comparison failed, not a numeric difference between '";
      *ErrorMsg += F1P[0];
      *ErrorMsg += "' and '";
      *ErrorMsg += F2P[0];
      *ErrorMsg += "'";
    }
    return true;
  }

  // Check to see if these are inside the absolute tolerance
  if (AbsTolerance < std::abs(V1-V2)) {
    // Nope, check the relative tolerance...
    double Diff;
    if (V2)
      Diff = std::abs(V1/V2 - 1.0);
    else if (V1)
      Diff = std::abs(V2/V1 - 1.0);
    else
      Diff = 0;  // Both zero.
    if (Diff > RelTolerance) {
      if (ErrorMsg) {
        *ErrorMsg = "Compared: " + ftostr(V1) + " and " + ftostr(V2) + "\n";
        *ErrorMsg += "abs. diff = " + ftostr(std::abs(V1-V2)) +
                     " rel.diff = " + ftostr(Diff) + "\n";
        *ErrorMsg += "Out of tolerance: rel/abs: " + ftostr(RelTolerance) +
                     "/" + ftostr(AbsTolerance);
      }
      return true;
    }
  }

  // Otherwise, advance our read pointers to the end of the numbers.
  F1P = F1NumEnd;  F2P = F2NumEnd;
  return false;
}

// PadFileIfNeeded - If the files are not identical, we will have to be doing
// numeric comparisons in here.  There are bad cases involved where we (i.e.,
// strtod) might run off the beginning or end of the file if it starts or ends
// with a number.  Because of this, if needed, we pad the file so that it starts
// and ends with a null character.
static void PadFileIfNeeded(char *&FileStart, char *&FileEnd, char *&FP) {
  if (FileStart-FileEnd < 2 ||
      isNumberChar(FileStart[0]) || isNumberChar(FileEnd[-1])) {
    unsigned FileLen = FileEnd-FileStart;
    char *NewFile = new char[FileLen+2];
    NewFile[0] = 0;              // Add null padding
    NewFile[FileLen+1] = 0;      // Add null padding
    memcpy(NewFile+1, FileStart, FileLen);
    FP = NewFile+(FP-FileStart)+1;
    FileStart = NewFile+1;
    FileEnd = FileStart+FileLen;
  }
}

/// DiffFilesWithTolerance - Compare the two files specified, returning 0 if the
/// files match, 1 if they are different, and 2 if there is a file error.  This
/// function differs from DiffFiles in that you can specify an absolete and
/// relative FP error that is allowed to exist.  If you specify a string to fill
/// in for the error option, it will set the string to an error message if an
/// error occurs, allowing the caller to distinguish between a failed diff and a
/// file system error.
///
int llvm::DiffFilesWithTolerance(const sys::PathWithStatus &FileA,
                                 const sys::PathWithStatus &FileB,
                                 double AbsTol, double RelTol,
                                 std::string *Error) {
  const sys::FileStatus *FileAStat = FileA.getFileStatus(false, Error);
  if (!FileAStat)
    return 2;
  const sys::FileStatus *FileBStat = FileB.getFileStatus(false, Error);
  if (!FileBStat)
    return 2;

  // Check for zero length files because some systems croak when you try to
  // mmap an empty file.
  size_t A_size = FileAStat->getSize();
  size_t B_size = FileBStat->getSize();

  // If they are both zero sized then they're the same
  if (A_size == 0 && B_size == 0)
    return 0;

  // If only one of them is zero sized then they can't be the same
  if ((A_size == 0 || B_size == 0)) {
    if (Error)
      *Error = "Files differ: one is zero-sized, the other isn't";
    return 1;
  }

  // Now its safe to mmap the files into memory becasue both files
  // have a non-zero size.
  sys::MappedFile F1;
  if (F1.open(FileA, sys::MappedFile::READ_ACCESS, Error))
    return 2;
  sys::MappedFile F2;
  if (F2.open(FileB, sys::MappedFile::READ_ACCESS, Error))
    return 2;
  if (!F1.map(Error))
    return 2;
  if (!F2.map(Error))
    return 2;

  // Okay, now that we opened the files, scan them for the first difference.
  char *File1Start = F1.charBase();
  char *File2Start = F2.charBase();
  char *File1End = File1Start+A_size;
  char *File2End = File2Start+B_size;
  char *F1P = File1Start;
  char *F2P = File2Start;

  if (A_size == B_size) {
    // Are the buffers identical?
    if (std::memcmp(File1Start, File2Start, A_size) == 0)
      return 0;

    if (AbsTol == 0 && RelTol == 0) {
      if (Error)
        *Error = "Files differ without tolerance allowance";
      return 1;   // Files different!
    }
  }

  char *OrigFile1Start = File1Start;
  char *OrigFile2Start = File2Start;

  // If the files need padding, do so now.
  PadFileIfNeeded(File1Start, File1End, F1P);
  PadFileIfNeeded(File2Start, File2End, F2P);

  bool CompareFailed = false;
  while (1) {
    // Scan for the end of file or next difference.
    while (F1P < File1End && F2P < File2End && *F1P == *F2P)
      ++F1P, ++F2P;

    if (F1P >= File1End || F2P >= File2End) break;

    // Okay, we must have found a difference.  Backup to the start of the
    // current number each stream is at so that we can compare from the
    // beginning.
    F1P = BackupNumber(F1P, File1Start);
    F2P = BackupNumber(F2P, File2Start);

    // Now that we are at the start of the numbers, compare them, exiting if
    // they don't match.
    if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) {
      CompareFailed = true;
      break;
    }
  }

  // Okay, we reached the end of file.  If both files are at the end, we
  // succeeded.
  bool F1AtEnd = F1P >= File1End;
  bool F2AtEnd = F2P >= File2End;
  if (!CompareFailed && (!F1AtEnd || !F2AtEnd)) {
    // Else, we might have run off the end due to a number: backup and retry.
    if (F1AtEnd && isNumberChar(F1P[-1])) --F1P;
    if (F2AtEnd && isNumberChar(F2P[-1])) --F2P;
    F1P = BackupNumber(F1P, File1Start);
    F2P = BackupNumber(F2P, File2Start);

    // Now that we are at the start of the numbers, compare them, exiting if
    // they don't match.
    if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error))
      CompareFailed = true;

    // If we found the end, we succeeded.
    if (F1P < File1End || F2P < File2End)
      CompareFailed = true;
  }

  if (OrigFile1Start != File1Start)
    delete[] (File1Start-1);   // Back up past null byte
  if (OrigFile2Start != File2Start)
    delete[] (File2Start-1);   // Back up past null byte
  return CompareFailed;
}
<commit_msg>Simplify the code and fix a typo.<commit_after>//===- Support/FileUtilities.cpp - File System Utilities ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a family of utility functions which are useful for doing
// various things with files.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/FileUtilities.h"
#include "llvm/System/Path.h"
#include "llvm/System/MappedFile.h"
#include "llvm/ADT/StringExtras.h"
#include <cstring>
#include <cctype>
using namespace llvm;

static bool isSignedChar(char C) {
  return (C == '+' || C == '-');
}

static bool isExponentChar(char C) {
  switch (C) {
  case 'D':  // Strange exponential notation.
  case 'd':  // Strange exponential notation.
  case 'e':
  case 'E': return true;
  default: return false;
  }
}

static bool isNumberChar(char C) {
  switch (C) {
  case '0': case '1': case '2': case '3': case '4':
  case '5': case '6': case '7': case '8': case '9':
  case '.': return true;
  default: return isSignedChar(C) || isExponentChar(C);
  }
}

static char *BackupNumber(char *Pos, char *FirstChar) {
  // If we didn't stop in the middle of a number, don't backup.
  if (!isNumberChar(*Pos)) return Pos;

  // Otherwise, return to the start of the number.
  while (Pos > FirstChar && isNumberChar(Pos[-1])) {
    --Pos;
    if (Pos > FirstChar && isSignedChar(Pos[0]) && !isExponentChar(Pos[-1]))
      break;
  }
  return Pos;
}

/// CompareNumbers - compare two numbers, returning true if they are different.
static bool CompareNumbers(char *&F1P, char *&F2P, char *F1End, char *F2End,
                           double AbsTolerance, double RelTolerance,
                           std::string *ErrorMsg) {
  char *F1NumEnd, *F2NumEnd;
  double V1 = 0.0, V2 = 0.0;

  // If one of the positions is at a space and the other isn't, chomp up 'til
  // the end of the space.
  while (isspace(*F1P) && F1P != F1End)
    ++F1P;
  while (isspace(*F2P) && F2P != F2End)
    ++F2P;

  // If we stop on numbers, compare their difference.  Note that some ugliness
  // is built into this to permit support for numbers that use "D" or "d" as
  // their exponential marker, e.g. "1.234D45".  This occurs in 200.sixtrack in
  // spec2k.
  if (isNumberChar(*F1P) && isNumberChar(*F2P)) {
    bool isDNotation;
    do {
      isDNotation = false;
      V1 = strtod(F1P, &F1NumEnd);
      V2 = strtod(F2P, &F2NumEnd);

      if (*F1NumEnd == 'D' || *F1NumEnd == 'd') {
        *F1NumEnd = 'e';  // Strange exponential notation!
        isDNotation = true;
      }
      if (*F2NumEnd == 'D' || *F2NumEnd == 'd') {
        *F2NumEnd = 'e';  // Strange exponential notation!
        isDNotation = true;
      }
    } while (isDNotation);
  } else {
    // Otherwise, the diff failed.
    F1NumEnd = F1P;
    F2NumEnd = F2P;
  }

  if (F1NumEnd == F1P || F2NumEnd == F2P) {
    if (ErrorMsg) {
      *ErrorMsg = "FP Comparison failed, not a numeric difference between '";
      *ErrorMsg += F1P[0];
      *ErrorMsg += "' and '";
      *ErrorMsg += F2P[0];
      *ErrorMsg += "'";
    }
    return true;
  }

  // Check to see if these are inside the absolute tolerance
  if (AbsTolerance < std::abs(V1-V2)) {
    // Nope, check the relative tolerance...
    double Diff;
    if (V2)
      Diff = std::abs(V1/V2 - 1.0);
    else if (V1)
      Diff = std::abs(V2/V1 - 1.0);
    else
      Diff = 0;  // Both zero.
    if (Diff > RelTolerance) {
      if (ErrorMsg) {
        *ErrorMsg = "Compared: " + ftostr(V1) + " and " + ftostr(V2) + "\n";
        *ErrorMsg += "abs. diff = " + ftostr(std::abs(V1-V2)) +
                     " rel.diff = " + ftostr(Diff) + "\n";
        *ErrorMsg += "Out of tolerance: rel/abs: " + ftostr(RelTolerance) +
                     "/" + ftostr(AbsTolerance);
      }
      return true;
    }
  }

  // Otherwise, advance our read pointers to the end of the numbers.
  F1P = F1NumEnd;  F2P = F2NumEnd;
  return false;
}

// PadFileIfNeeded - If the files are not identical, we will have to be doing
// numeric comparisons in here.  There are bad cases involved where we (i.e.,
// strtod) might run off the beginning or end of the file if it starts or ends
// with a number.  Because of this, if needed, we pad the file so that it starts
// and ends with a null character.
static void PadFileIfNeeded(char *&FileStart, char *&FileEnd, char *&FP) {
  if (FileStart-FileEnd < 2 ||
      isNumberChar(FileStart[0]) || isNumberChar(FileEnd[-1])) {
    unsigned FileLen = FileEnd-FileStart;
    char *NewFile = new char[FileLen+2];
    NewFile[0] = 0;              // Add null padding
    NewFile[FileLen+1] = 0;      // Add null padding
    memcpy(NewFile+1, FileStart, FileLen);
    FP = NewFile+(FP-FileStart)+1;
    FileStart = NewFile+1;
    FileEnd = FileStart+FileLen;
  }
}

/// DiffFilesWithTolerance - Compare the two files specified, returning 0 if the
/// files match, 1 if they are different, and 2 if there is a file error.  This
/// function differs from DiffFiles in that you can specify an absolete and
/// relative FP error that is allowed to exist.  If you specify a string to fill
/// in for the error option, it will set the string to an error message if an
/// error occurs, allowing the caller to distinguish between a failed diff and a
/// file system error.
///
int llvm::DiffFilesWithTolerance(const sys::PathWithStatus &FileA,
                                 const sys::PathWithStatus &FileB,
                                 double AbsTol, double RelTol,
                                 std::string *Error) {
  const sys::FileStatus *FileAStat = FileA.getFileStatus(false, Error);
  if (!FileAStat)
    return 2;
  const sys::FileStatus *FileBStat = FileB.getFileStatus(false, Error);
  if (!FileBStat)
    return 2;

  // Check for zero length files because some systems croak when you try to
  // mmap an empty file.
  size_t A_size = FileAStat->getSize();
  size_t B_size = FileBStat->getSize();

  // If they are both zero sized then they're the same
  if (A_size == 0 && B_size == 0)
    return 0;

  // If only one of them is zero sized then they can't be the same
  if ((A_size == 0 || B_size == 0)) {
    if (Error)
      *Error = "Files differ: one is zero-sized, the other isn't";
    return 1;
  }

  // Now its safe to mmap the files into memory becasue both files
  // have a non-zero size.
  sys::MappedFile F1;
  if (F1.open(FileA, sys::MappedFile::READ_ACCESS, Error))
    return 2;
  sys::MappedFile F2;
  if (F2.open(FileB, sys::MappedFile::READ_ACCESS, Error))
    return 2;
  if (!F1.map(Error))
    return 2;
  if (!F2.map(Error))
    return 2;

  // Okay, now that we opened the files, scan them for the first difference.
  char *File1Start = F1.charBase();
  char *File2Start = F2.charBase();
  char *File1End = File1Start+A_size;
  char *File2End = File2Start+B_size;
  char *F1P = File1Start;
  char *F2P = File2Start;

  if (A_size == B_size) {
    // Are the buffers identical?
    if (std::memcmp(File1Start, File2Start, A_size) == 0)
      return 0;

    if (AbsTol == 0 && RelTol == 0) {
      if (Error)
        *Error = "Files differ without tolerance allowance";
      return 1;   // Files different!
    }
  }

  char *OrigFile1Start = File1Start;
  char *OrigFile2Start = File2Start;

  // If the files need padding, do so now.
  PadFileIfNeeded(File1Start, File1End, F1P);
  PadFileIfNeeded(File2Start, File2End, F2P);

  bool CompareFailed = false;
  while (1) {
    // Scan for the end of file or next difference.
    while (F1P < File1End && F2P < File2End && *F1P == *F2P)
      ++F1P, ++F2P;

    if (F1P >= File1End || F2P >= File2End) break;

    // Okay, we must have found a difference.  Backup to the start of the
    // current number each stream is at so that we can compare from the
    // beginning.
    F1P = BackupNumber(F1P, File1Start);
    F2P = BackupNumber(F2P, File2Start);

    // Now that we are at the start of the numbers, compare them, exiting if
    // they don't match.
    if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) {
      CompareFailed = true;
      break;
    }
  }

  // Okay, we reached the end of file.  If both files are at the end, we
  // succeeded.
  bool F1AtEnd = F1P >= File1End;
  bool F2AtEnd = F2P >= File2End;
  if (!CompareFailed && (!F1AtEnd || !F2AtEnd)) {
    // Else, we might have run off the end due to a number: backup and retry.
    if (F1AtEnd && isNumberChar(F1P[-1])) --F1P;
    if (F2AtEnd && isNumberChar(F2P[-1])) --F2P;
    F1P = BackupNumber(F1P, File1Start);
    F2P = BackupNumber(F2P, File2Start);

    // Now that we are at the start of the numbers, compare them, exiting if
    // they don't match.
    if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error))
      CompareFailed = true;

    // If we found the end, we succeeded.
    if (F1P < File1End || F2P < File2End)
      CompareFailed = true;
  }

  if (OrigFile1Start != File1Start)
    delete[] (File1Start-1);   // Back up past null byte
  if (OrigFile2Start != File2Start)
    delete[] (File2Start-1);   // Back up past null byte
  return CompareFailed;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "cntsimcontactremoverequest.h"
#include "cntsymbiansimengine.h"
#include "cntsimstore.h"
#include <qcontactremoverequest.h>
#include <QDebug>

CntSimContactRemoveRequest::CntSimContactRemoveRequest(CntSymbianSimEngine *engine, QContactRemoveRequest *req)
    :CntAbstractSimRequest(engine, req)
{
    connect( simStore(), SIGNAL(removeComplete(QContactManager::Error)),
        this, SLOT(removeComplete(QContactManager::Error)), Qt::QueuedConnection );

    connect( simStore(), SIGNAL(getReservedSlotsComplete(QList<int>, QContactManager::Error)),
        this, SLOT(getReservedSlotsComplete(QList<int>, QContactManager::Error)), Qt::QueuedConnection );
}

CntSimContactRemoveRequest::~CntSimContactRemoveRequest()
{
    cancel();
}

void CntSimContactRemoveRequest::run()
{
    QContactRemoveRequest *r = req<QContactRemoveRequest>();

    if (!r->isActive())
        return;

    m_contactIds = r->contactIds();
    m_errorMap.clear();
    m_index = 0;
#ifdef SYMBIANSIM_BACKEND_CHECK_BEFORE_REMOVE
    m_reservedSlots.clear();
    getReservedSlots();
#else
    removeNext();
#endif
}

void CntSimContactRemoveRequest::removeComplete(QContactManager::Error error)
{
    if (!req()->isActive())
        return;

    if (error)
        m_errorMap.insert(m_index, error);

    m_index++;
    singleShotTimer(KRequestDelay, this, SLOT(removeNext()));
}

void CntSimContactRemoveRequest::removeNext()
{
    QContactRemoveRequest *r = req<QContactRemoveRequest>();

    if (!r->isActive())
        return;

    if (r->contactIds().count() == 0) {
        QContactManagerEngine::updateContactRemoveRequest(r, QContactManager::BadArgumentError, m_errorMap, QContactAbstractRequest::FinishedState);
        return;
    }

    // All contacts removed?
    if (m_index >= m_contactIds.count())
    {
        // Take first error from errormap (if any)
        QContactManager::Error error = QContactManager::NoError;
        if (m_errorMap.count())
            error = m_errorMap.begin().value();

        QContactManagerEngine::updateContactRemoveRequest(r, error, m_errorMap, QContactAbstractRequest::FinishedState);
        return;
    }

    // Remove next contact
    QContactLocalId contactId = m_contactIds.at(m_index);
    QContactManager::Error error = QContactManager::NoError;

#ifdef SYMBIANSIM_BACKEND_CHECK_BEFORE_REMOVE
    if (m_reservedSlots.contains(contactId))
        simStore()->remove(contactId, error);
    else
        error = QContactManager::DoesNotExistError;
#else
    simStore()->remove(contactId, &error);
#endif

    if (error) {
        m_errorMap.insert(m_index, error);
        m_index++;
        singleShotTimer(KRequestDelay, this, SLOT(removeNext()));
    }
}

void CntSimContactRemoveRequest::getReservedSlotsComplete(QList<int> reservedSlots, QContactManager::Error error)
{
    QContactRemoveRequest *r = req<QContactRemoveRequest>();

    if (!r->isActive())
        return;

    if (error != QContactManager::NoError && error != QContactManager::DoesNotExistError) {
        QContactManagerEngine::updateContactRemoveRequest(r, error, m_errorMap, QContactAbstractRequest::FinishedState);
        return;
    }

    m_reservedSlots = reservedSlots;
    singleShotTimer(KRequestDelay, this, SLOT(removeNext()));
}

void CntSimContactRemoveRequest::getReservedSlots()
{
    QContactRemoveRequest *r = req<QContactRemoveRequest>();

    if (!r->isActive())
        return;

    QContactManager::Error error = QContactManager::NoError;
    if (!simStore()->getReservedSlots(&error)) {
        QContactManagerEngine::updateContactRemoveRequest(r, error, m_errorMap, QContactAbstractRequest::FinishedState);
    }
}
<commit_msg>Symbian: Somebody missed spot with the error reference to pointer change. (cherry picked from commit caba1a6b9b4afccdf622ce2f73a56fccc6674174)<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "cntsimcontactremoverequest.h"
#include "cntsymbiansimengine.h"
#include "cntsimstore.h"
#include <qcontactremoverequest.h>
#include <QDebug>

CntSimContactRemoveRequest::CntSimContactRemoveRequest(CntSymbianSimEngine *engine, QContactRemoveRequest *req)
    :CntAbstractSimRequest(engine, req)
{
    connect( simStore(), SIGNAL(removeComplete(QContactManager::Error)),
        this, SLOT(removeComplete(QContactManager::Error)), Qt::QueuedConnection );

    connect( simStore(), SIGNAL(getReservedSlotsComplete(QList<int>, QContactManager::Error)),
        this, SLOT(getReservedSlotsComplete(QList<int>, QContactManager::Error)), Qt::QueuedConnection );
}

CntSimContactRemoveRequest::~CntSimContactRemoveRequest()
{
    cancel();
}

void CntSimContactRemoveRequest::run()
{
    QContactRemoveRequest *r = req<QContactRemoveRequest>();

    if (!r->isActive())
        return;

    m_contactIds = r->contactIds();
    m_errorMap.clear();
    m_index = 0;
#ifdef SYMBIANSIM_BACKEND_CHECK_BEFORE_REMOVE
    m_reservedSlots.clear();
    getReservedSlots();
#else
    removeNext();
#endif
}

void CntSimContactRemoveRequest::removeComplete(QContactManager::Error error)
{
    if (!req()->isActive())
        return;

    if (error)
        m_errorMap.insert(m_index, error);

    m_index++;
    singleShotTimer(KRequestDelay, this, SLOT(removeNext()));
}

void CntSimContactRemoveRequest::removeNext()
{
    QContactRemoveRequest *r = req<QContactRemoveRequest>();

    if (!r->isActive())
        return;

    if (r->contactIds().count() == 0) {
        QContactManagerEngine::updateContactRemoveRequest(r, QContactManager::BadArgumentError, m_errorMap, QContactAbstractRequest::FinishedState);
        return;
    }

    // All contacts removed?
    if (m_index >= m_contactIds.count())
    {
        // Take first error from errormap (if any)
        QContactManager::Error error = QContactManager::NoError;
        if (m_errorMap.count())
            error = m_errorMap.begin().value();

        QContactManagerEngine::updateContactRemoveRequest(r, error, m_errorMap, QContactAbstractRequest::FinishedState);
        return;
    }

    // Remove next contact
    QContactLocalId contactId = m_contactIds.at(m_index);
    QContactManager::Error error = QContactManager::NoError;

#ifdef SYMBIANSIM_BACKEND_CHECK_BEFORE_REMOVE
    if (m_reservedSlots.contains(contactId))
        simStore()->remove(contactId, &error);
    else
        error = QContactManager::DoesNotExistError;
#else
    simStore()->remove(contactId, &error);
#endif

    if (error) {
        m_errorMap.insert(m_index, error);
        m_index++;
        singleShotTimer(KRequestDelay, this, SLOT(removeNext()));
    }
}

void CntSimContactRemoveRequest::getReservedSlotsComplete(QList<int> reservedSlots, QContactManager::Error error)
{
    QContactRemoveRequest *r = req<QContactRemoveRequest>();

    if (!r->isActive())
        return;

    if (error != QContactManager::NoError && error != QContactManager::DoesNotExistError) {
        QContactManagerEngine::updateContactRemoveRequest(r, error, m_errorMap, QContactAbstractRequest::FinishedState);
        return;
    }

    m_reservedSlots = reservedSlots;
    singleShotTimer(KRequestDelay, this, SLOT(removeNext()));
}

void CntSimContactRemoveRequest::getReservedSlots()
{
    QContactRemoveRequest *r = req<QContactRemoveRequest>();

    if (!r->isActive())
        return;

    QContactManager::Error error = QContactManager::NoError;
    if (!simStore()->getReservedSlots(&error)) {
        QContactManagerEngine::updateContactRemoveRequest(r, error, m_errorMap, QContactAbstractRequest::FinishedState);
    }
}
<|endoftext|>


<commit_before>#include "bench_framework.hpp"
#include <mapnik/map.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
#include <stdexcept>

class test : public benchmark::test_case
{
    std::string xml_;
    mapnik::box2d<double> extent_;
    mapnik::value_integer width_;
    mapnik::value_integer height_;
    std::string preview_;
public:
    test(mapnik::parameters const& params)
     : test_case(params),
       xml_(),
       extent_(),
       width_(*params.get<mapnik::value_integer>("width",256)),
       height_(*params.get<mapnik::value_integer>("height",256)),
       preview_(*params.get<std::string>("preview",""))
      {
        boost::optional<std::string> map = params.get<std::string>("map");
        if (!map)
        {
            throw std::runtime_error("please provide a --map=<path to xml> arg");
        }
        xml_ = *map;

        boost::optional<std::string> ext = params.get<std::string>("extent");
        if (ext && !ext->empty())
        {
            if (!extent_.from_string(*ext))
                throw std::runtime_error("could not parse `extent` string" + *ext);
        }
        else
        {
            throw std::runtime_error("please provide a --extent=<minx,miny,maxx,maxy> arg");
        }

      }
    bool validate() const
    {
        mapnik::Map m(width_,height_);
        mapnik::load_map(m,xml_,true);
        m.zoom_to_box(extent_);
        mapnik::image_32 im(m.width(),m.height());
        mapnik::agg_renderer<mapnik::image_32> ren(m,im);
        ren.apply();
        if (!preview_.empty()) mapnik::save_to_file(im,preview_);
        return true;
    }
    void operator()() const
    {
        mapnik::Map m(width_,height_);
        mapnik::load_map(m,xml_);
        m.zoom_to_box(extent_);
        for (unsigned i=0;i<iterations_;++i)
        {
            mapnik::image_32 im(m.width(),m.height());
            mapnik::agg_renderer<mapnik::image_32> ren(m,im);
            ren.apply();
        }
    }
};

int main(int argc, char** argv)
{
    try
    {
        mapnik::parameters params;
        benchmark::handle_args(argc,argv,params);
        boost::optional<std::string> name = params.get<std::string>("name");
        if (!name)
        {
            std::clog << "please provide a name for this test\n";
            return -1;
        }
        mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
        {
            test test_runner(params);
            run(test_runner,*name);
        }
    }
    catch (std::exception const& ex)
    {
        std::clog << ex.what() << "\n";
        return -1;
    }
    return 0;
}
<commit_msg>make rendering bench shell easy to run<commit_after>#include "bench_framework.hpp"
#include <mapnik/map.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <stdexcept>

class test : public benchmark::test_case
{
    std::string xml_;
    mapnik::box2d<double> extent_;
    mapnik::value_integer width_;
    mapnik::value_integer height_;
    std::string preview_;
public:
    test(mapnik::parameters const& params)
     : test_case(params),
       xml_(),
       extent_(),
       width_(*params.get<mapnik::value_integer>("width",256)),
       height_(*params.get<mapnik::value_integer>("height",256)),
       preview_(*params.get<std::string>("preview",""))
      {
        boost::optional<std::string> map = params.get<std::string>("map");
        if (!map)
        {
            throw std::runtime_error("please provide a --map=<path to xml> arg");
        }
        xml_ = *map;

        boost::optional<std::string> ext = params.get<std::string>("extent");
        if (ext && !ext->empty())
        {
            if (!extent_.from_string(*ext))
                throw std::runtime_error("could not parse `extent` string" + *ext);
        }
        /*
        else
        {
            throw std::runtime_error("please provide a --extent=<minx,miny,maxx,maxy> arg");
        }*/

      }
    bool validate() const
    {
        mapnik::Map m(width_,height_);
        mapnik::load_map(m,xml_,true);
        if (extent_.valid()) {
            m.zoom_to_box(extent_);
        } else {
            m.zoom_all();
        }
        mapnik::image_32 im(m.width(),m.height());
        mapnik::agg_renderer<mapnik::image_32> ren(m,im);
        ren.apply();
        if (!preview_.empty()) mapnik::save_to_file(im,preview_);
        return true;
    }
    void operator()() const
    {
        mapnik::Map m(width_,height_);
        mapnik::load_map(m,xml_);
        if (extent_.valid()) {
            m.zoom_to_box(extent_);
        } else {
            m.zoom_all();
        }
        for (unsigned i=0;i<iterations_;++i)
        {
            mapnik::image_32 im(m.width(),m.height());
            mapnik::agg_renderer<mapnik::image_32> ren(m,im);
            ren.apply();
        }
    }
};

int main(int argc, char** argv)
{
    try
    {
        mapnik::parameters params;
        benchmark::handle_args(argc,argv,params);
        boost::optional<std::string> name = params.get<std::string>("name");
        if (!name)
        {
            std::clog << "please provide a name for this test\n";
            return -1;
        }
        mapnik::freetype_engine::register_fonts("./fonts/",true);
        mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
        {
            test test_runner(params);
            run(test_runner,*name);
        }
    }
    catch (std::exception const& ex)
    {
        std::clog << ex.what() << "\n";
        return -1;
    }
    return 0;
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <asmjit/asmjit.h>
#include <vector>
#include <stack>
using namespace asmjit;
using namespace asmjit::x86;

int main(int argc, char *argv[]) {
	std::vector<char> cells(1024); // construct 256 cells
	std::stack<std::pair<Label, Label>> block_labels;
	JitRuntime runtime;
	X86Compiler c(&runtime);

	cells.assign(1024, 0);

	const char code[] = "+++[->,.<]"; //"++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";

	c.addFunc(kFuncConvHost, FuncBuilder1<void, char*>());

	X86GpVar cells_ptr(c, kVarTypeIntPtr, "cells_ptr");
	c.setArg(0, cells_ptr);
	X86GpVar a(c, kVarTypeInt8, "a");
	X86GpVar b(c, kVarTypeInt32, "b");

	X86GpVar _putchar(c, kVarTypeIntPtr, "_putchar");
	c.mov(_putchar, intptr_t(&putchar));

	X86GpVar _getchar(c, kVarTypeIntPtr, "_getchar");
	c.mov(_getchar, intptr_t(&getchar));

	//Label lbl(c);
	//Label lbl2(c);

	for(char ch : code) {
		switch(ch) {
			case '+':
				c.inc(byte_ptr(cells_ptr));
				break;
			case '-':
				c.dec(byte_ptr(cells_ptr));
				break;
			case '<':
				c.dec(cells_ptr);
				break;
			case '>':
				c.inc(cells_ptr);
				break;
			case '.': {
				c.mov(b, byte_ptr(cells_ptr));
				X86CallNode *call = c.call(_putchar, kX86FuncConvCDecl, FuncBuilder1<int, int>());
				call->setArg(0, b);
				break;
			}
			case ',': {
				X86CallNode *call = c.call(_getchar, kX86FuncConvCDecl, FuncBuilder0<int>());
				call->setRet(0, b);
				c.mov(byte_ptr(cells_ptr), b);
				break;
			}
			case '[': {
				// a pair of addresses for (start of loop, end of loop)
				block_labels.emplace(std::make_pair(Label(c), Label(c)));
				auto& label_pair = block_labels.top();

				c.bind(label_pair.first);
				c.mov(a, byte_ptr(cells_ptr));
				c.test(a, a);
				c.jz(label_pair.second);
				break;
			}
			case ']': {
				auto& label_pair = block_labels.top();
				block_labels.pop();
				c.jmp(label_pair.first);
				c.bind(label_pair.second); // back-patch the label to refer to here (after the ])
				break;
			}
			case '\0':
				break;
			default:
				printf("error: unknown char '%c'\n", ch);
				return 1;
		}
	}

	c.endFunc();

	void* funcPtr = c.make();
	typedef int (*FuncType)(char *ptr);

	// run JITed code
	FuncType func = asmjit_cast<FuncType>(funcPtr);
	func(cells.data());

	runtime.release((void*)func);

	return 0;
}<commit_msg>get input from a file<commit_after>#include <cstdio>
#include <vector>
#include <stack>
#include <fstream>
#include <asmjit/asmjit.h>
using namespace asmjit;
using namespace asmjit::x86;

int main(int argc, char *argv[]) {
	std::ifstream fs;
	std::vector<char> cells(1024); // construct 1024 cells
	std::stack<std::pair<Label, Label>> block_labels;
	JitRuntime runtime;
	X86Compiler c(&runtime);
	cells.assign(1024, 0);

	if(argc < 2) {
		printf("USAGE: %s FILE", argv[0]);
		return 1;
	}

	fs.open(argv[1]);

	c.addFunc(kFuncConvHost, FuncBuilder1<void, char*>());

	X86GpVar cells_ptr(c, kVarTypeIntPtr, "cells_ptr");
	c.setArg(0, cells_ptr);
	X86GpVar a(c, kVarTypeInt8, "a");
	X86GpVar b(c, kVarTypeInt32, "b");

	X86GpVar _putchar(c, kVarTypeIntPtr, "_putchar");
	c.mov(_putchar, intptr_t(&putchar));

	X86GpVar _getchar(c, kVarTypeIntPtr, "_getchar");
	c.mov(_getchar, intptr_t(&getchar));

	char ch;
	while(fs >> ch) {
		switch(ch) {
			case '+':
				c.inc(byte_ptr(cells_ptr));
				break;
			case '-':
				c.dec(byte_ptr(cells_ptr));
				break;
			case '<':
				c.dec(cells_ptr);
				break;
			case '>':
				c.inc(cells_ptr);
				break;
			case '.': {
				c.mov(b, byte_ptr(cells_ptr));
				X86CallNode *call = c.call(_putchar, kX86FuncConvCDecl, FuncBuilder1<int, int>());
				call->setArg(0, b);
				break;
			}
			case ',': {
				X86CallNode *call = c.call(_getchar, kX86FuncConvCDecl, FuncBuilder0<int>());
				call->setRet(0, b);
				c.mov(byte_ptr(cells_ptr), b);
				break;
			}
			case '[': {
				// a pair of addresses for (start of loop, end of loop)
				block_labels.emplace(std::make_pair(Label(c), Label(c)));
				auto& label_pair = block_labels.top();

				c.bind(label_pair.first);
				c.mov(a, byte_ptr(cells_ptr));
				c.test(a, a);
				c.jz(label_pair.second);
				break;
			}
			case ']': {
				auto& label_pair = block_labels.top();
				block_labels.pop();
				c.jmp(label_pair.first);
				c.bind(label_pair.second); // back-patch the label to refer to here (after the ])
				break;
			}
			case '\0':
				break;
			default:
				printf("error: unknown char '%c'\n", ch);
				return 1;
		}
	}

	c.endFunc();

	void* funcPtr = c.make();
	typedef int (*FuncType)(char *ptr);

	// run JITed code
	FuncType func = asmjit_cast<FuncType>(funcPtr);
	func(cells.data());

	runtime.release((void*)func);

	return 0;
}<|endoftext|>


<commit_before>// @(#)root/meta:$Id$
// Author: Rene Brun   04/02/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TMethodArg.h"
#include "TROOT.h"
#include "TInterpreter.h"
#include "Strlen.h"
#include "TMethod.h"
#include "TMethodCall.h"
#include "TDataMember.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  Each ROOT method (see TMethod) has a linked list of its arguments.  //
//  This class describes one single method argument.                    //
//  The method argument info is obtained via the CINT api.              //
//  See class TCling.                                                    //
//                                                                      //
//  The method argument information is used a.o. in the TContextMenu    //
//  and THtml classes.                                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

ClassImp(TMethodArg)

////////////////////////////////////////////////////////////////////////////////
/// Default TMethodArg ctor. TMethodArgs are constructed in TFunction
/// via a call to TCling::CreateListOfMethodArgs().

TMethodArg::TMethodArg(MethodArgInfo_t *info, TFunction *method) : TDictionary()
{
   fDataMember = 0;
   fInfo       = info;
   fMethod     = method;
   if (fInfo) {
      SetName(gCling->MethodArgInfo_Name(fInfo));
      SetTitle(gCling->MethodArgInfo_TypeName(fInfo));
   }
}

////////////////////////////////////////////////////////////////////////////////
/// TMethodArg dtor deletes adopted CINT MethodArgInfo object.

TMethodArg::~TMethodArg()
{
   if (fInfo) gCling->MethodArgInfo_Delete(fInfo);
}

////////////////////////////////////////////////////////////////////////////////
/// Get default value of method argument.

const char *TMethodArg::GetDefault() const
{
   return gCling->MethodArgInfo_DefaultValue(fInfo);
}

////////////////////////////////////////////////////////////////////////////////
/// Get type of method argument, e.g.: "class TDirectory*" -> "TDirectory"
/// Result needs to be used or copied immediately.

const char *TMethodArg::GetTypeName() const
{
   return gCling->TypeName(gCling->MethodArgInfo_TypeName(fInfo));
}

////////////////////////////////////////////////////////////////////////////////
/// Get full type description of method argument, e.g.: "class TDirectory*".

const char *TMethodArg::GetFullTypeName() const
{
   return gCling->MethodArgInfo_TypeName(fInfo);
}

////////////////////////////////////////////////////////////////////////////////
/// Get the normalized name of the return type.  A normalized name is fully
/// qualified and has all typedef desugared except for the 'special' typedef
/// which include Double32_t, Float16_t, [U]Long64_t and std::string.  It
/// also has std:: removed [This is subject to change].
///

std::string TMethodArg::GetTypeNormalizedName() const
{
   return gCling->MethodArgInfo_TypeNormalizedName(fInfo);
}

////////////////////////////////////////////////////////////////////////////////
/// Get property description word. For meaning of bits see EProperty.

Long_t TMethodArg::Property() const
{
   return gCling->MethodArgInfo_Property(fInfo);
}

////////////////////////////////////////////////////////////////////////////////
/// Returns list of possible options - according to pointed datamember.
/// If there is no datamember field assigned to this methodarg - returns 0.

TList *TMethodArg::GetOptions() const
{
   return (TList*)(fDataMember ? fDataMember->GetOptions() : 0);
}

////////////////////////////////////////////////////////////////////////////////
/// Returns TDataMember pointed by this methodarg.
/// If you want to specify list of options or current value for your
/// MethodArg (i.e. it is used as initial values in argument-asking dialogs
/// popped up from context-meny),you can get this value from one of data
/// members of the class.
/// The only restriction is, that this DataMember object must have its
/// Getter/Setter methods set-up correctly - for details look at TDataMember.
/// To learn how to specify the data member to which the argument should
/// "point", look at TMethod. This is TMethod which sets up fDataMember,
/// so it could work correctly.

TDataMember *TMethodArg::GetDataMember() const
{
   return fDataMember;
}

////////////////////////////////////////////////////////////////////////////////
/// Update fInfo (to 0 for unloading and non-zero for reloading).
/// This takes ownership of 'info'

void TMethodArg::Update(MethodArgInfo_t *info)
{
   if (fInfo) gCling->MethodArgInfo_Delete(fInfo);
   fInfo = info;
   if (fInfo) {
      SetTitle(gCling->MethodArgInfo_TypeName(fInfo));
   }
}
<commit_msg>Doxygen<commit_after>// @(#)root/meta:$Id$
// Author: Rene Brun   04/02/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TMethodArg.h"
#include "TROOT.h"
#include "TInterpreter.h"
#include "Strlen.h"
#include "TMethod.h"
#include "TMethodCall.h"
#include "TDataMember.h"

/** \class TMethodArg
Each ROOT method (see TMethod) has a linked list of its arguments.
This class describes one single method argument.
The method argument info is obtained via the CINT api.
See class TCling.

The method argument information is used a.o. in the TContextMenu
and THtml classes.
*/

ClassImp(TMethodArg)

////////////////////////////////////////////////////////////////////////////////
/// Default TMethodArg ctor. TMethodArgs are constructed in TFunction
/// via a call to TCling::CreateListOfMethodArgs().

TMethodArg::TMethodArg(MethodArgInfo_t *info, TFunction *method) : TDictionary()
{
   fDataMember = 0;
   fInfo       = info;
   fMethod     = method;
   if (fInfo) {
      SetName(gCling->MethodArgInfo_Name(fInfo));
      SetTitle(gCling->MethodArgInfo_TypeName(fInfo));
   }
}

////////////////////////////////////////////////////////////////////////////////
/// TMethodArg dtor deletes adopted CINT MethodArgInfo object.

TMethodArg::~TMethodArg()
{
   if (fInfo) gCling->MethodArgInfo_Delete(fInfo);
}

////////////////////////////////////////////////////////////////////////////////
/// Get default value of method argument.

const char *TMethodArg::GetDefault() const
{
   return gCling->MethodArgInfo_DefaultValue(fInfo);
}

////////////////////////////////////////////////////////////////////////////////
/// Get type of method argument, e.g.: "class TDirectory*" -> "TDirectory"
/// Result needs to be used or copied immediately.

const char *TMethodArg::GetTypeName() const
{
   return gCling->TypeName(gCling->MethodArgInfo_TypeName(fInfo));
}

////////////////////////////////////////////////////////////////////////////////
/// Get full type description of method argument, e.g.: "class TDirectory*".

const char *TMethodArg::GetFullTypeName() const
{
   return gCling->MethodArgInfo_TypeName(fInfo);
}

////////////////////////////////////////////////////////////////////////////////
/// Get the normalized name of the return type. A normalized name is fully
/// qualified and has all typedef desugared except for the 'special' typedef
/// which include Double32_t, Float16_t, [U]Long64_t and std::string.  It
/// also has std:: removed [This is subject to change].

std::string TMethodArg::GetTypeNormalizedName() const
{
   return gCling->MethodArgInfo_TypeNormalizedName(fInfo);
}

////////////////////////////////////////////////////////////////////////////////
/// Get property description word. For meaning of bits see EProperty.

Long_t TMethodArg::Property() const
{
   return gCling->MethodArgInfo_Property(fInfo);
}

////////////////////////////////////////////////////////////////////////////////
/// Returns list of possible options - according to pointed datamember.
/// If there is no datamember field assigned to this methodarg - returns 0.

TList *TMethodArg::GetOptions() const
{
   return (TList*)(fDataMember ? fDataMember->GetOptions() : 0);
}

////////////////////////////////////////////////////////////////////////////////
/// Returns TDataMember pointed by this methodarg.
/// If you want to specify list of options or current value for your
/// MethodArg (i.e. it is used as initial values in argument-asking dialogs
/// popped up from context-meny),you can get this value from one of data
/// members of the class.
///
/// The only restriction is, that this DataMember object must have its
/// Getter/Setter methods set-up correctly - for details look at TDataMember.
/// To learn how to specify the data member to which the argument should
/// "point", look at TMethod. This is TMethod which sets up fDataMember,
/// so it could work correctly.

TDataMember *TMethodArg::GetDataMember() const
{
   return fDataMember;
}

////////////////////////////////////////////////////////////////////////////////
/// Update fInfo (to 0 for unloading and non-zero for reloading).
/// This takes ownership of 'info'

void TMethodArg::Update(MethodArgInfo_t *info)
{
   if (fInfo) gCling->MethodArgInfo_Delete(fInfo);
   fInfo = info;
   if (fInfo) {
      SetTitle(gCling->MethodArgInfo_TypeName(fInfo));
   }
}
<|endoftext|>