<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

//
// Buffered input and output streams
//
// Two abstract classes (data_source and data_sink) provide means
// to acquire bulk data from, or push bulk data to, some provider.
// These could be tied to a TCP connection, a disk file, or a memory
// buffer.
//
// Two concrete classes (input_stream and output_stream) buffer data
// from data_source and data_sink and provide easier means to process
// it.
//

#pragma once

#include <seastar/core/future.hh>
#include <seastar/core/temporary_buffer.hh>
#include <seastar/core/scattered_message.hh>
#include <seastar/util/std-compat.hh>

namespace seastar {

namespace net { class packet; }

class data_source_impl {
public:
    virtual ~data_source_impl() {}
    virtual future<temporary_buffer<char>> get() = 0;
    virtual future<temporary_buffer<char>> skip(uint64_t n);
    virtual future<> close() { return make_ready_future<>(); }
};

class data_source {
    std::unique_ptr<data_source_impl> _dsi;
protected:
    data_source_impl* impl() const { return _dsi.get(); }
public:
    data_source() = default;
    explicit data_source(std::unique_ptr<data_source_impl> dsi) : _dsi(std::move(dsi)) {}
    data_source(data_source&& x) = default;
    data_source& operator=(data_source&& x) = default;
    future<temporary_buffer<char>> get() { return _dsi->get(); }
    future<temporary_buffer<char>> skip(uint64_t n) { return _dsi->skip(n); }
    future<> close() { return _dsi->close(); }
};

class data_sink_impl {
public:
    virtual ~data_sink_impl() {}
    virtual temporary_buffer<char> allocate_buffer(size_t size) {
        return temporary_buffer<char>(size);
    }
    virtual future<> put(net::packet data) = 0;
    virtual future<> put(std::vector<temporary_buffer<char>> data) {
        net::packet p;
        p.reserve(data.size());
        for (auto& buf : data) {
            p = net::packet(std::move(p), net::fragment{buf.get_write(), buf.size()}, buf.release());
        }
        return put(std::move(p));
    }
    virtual future<> put(temporary_buffer<char> buf) {
        return put(net::packet(net::fragment{buf.get_write(), buf.size()}, buf.release()));
    }
    virtual future<> flush() {
        return make_ready_future<>();
    }
    virtual future<> close() = 0;
};

class data_sink {
    std::unique_ptr<data_sink_impl> _dsi;
public:
    data_sink() = default;
    explicit data_sink(std::unique_ptr<data_sink_impl> dsi) : _dsi(std::move(dsi)) {}
    data_sink(data_sink&& x) = default;
    data_sink& operator=(data_sink&& x) = default;
    temporary_buffer<char> allocate_buffer(size_t size) {
        return _dsi->allocate_buffer(size);
    }
    future<> put(std::vector<temporary_buffer<char>> data) {
        return _dsi->put(std::move(data));
    }
    future<> put(temporary_buffer<char> data) {
        return _dsi->put(std::move(data));
    }
    future<> put(net::packet p) {
        return _dsi->put(std::move(p));
    }
    future<> flush() {
        return _dsi->flush();
    }
    future<> close() { return _dsi->close(); }
};

struct continue_consuming {};

template <typename CharType>
class stop_consuming {
public:
    using tmp_buf = temporary_buffer<CharType>;
    explicit stop_consuming(tmp_buf buf) : _buf(std::move(buf)) {}

    tmp_buf& get_buffer() { return _buf; }
    const tmp_buf& get_buffer() const { return _buf; }
private:
    tmp_buf _buf;
};

class skip_bytes {
public:
    explicit skip_bytes(uint64_t v) : _value(v) {}
    uint64_t get_value() const { return _value; }
private:
    uint64_t _value;
};

template <typename CharType>
class consumption_result {
public:
    using stop_consuming_type = stop_consuming<CharType>;
    using consumption_variant = compat::variant<continue_consuming, stop_consuming_type, skip_bytes>;
    using tmp_buf = typename stop_consuming_type::tmp_buf;

    /*[[deprecated]]*/ consumption_result(compat::optional<tmp_buf> opt_buf) {
        if (opt_buf) {
            _result = stop_consuming_type{std::move(opt_buf.value())};
        }
    }

    consumption_result(const continue_consuming&) {}
    consumption_result(stop_consuming_type&& stop) : _result(std::move(stop)) {}
    consumption_result(skip_bytes&& skip) : _result(std::move(skip)) {}

    consumption_variant& get() { return _result; }
    const consumption_variant& get() const { return _result; }

private:
    consumption_variant _result;
};

// Consumer concept, for consume() method
GCC6_CONCEPT(
// The consumer should operate on the data given to it, and
// return a future "consumption result", which can be
//  - continue_consuming, if the consumer has consumed all the input given
// to it and is ready for more
//  - stop_consuming, when the consumer is done (and in that case
// the contained buffer is the unconsumed part of the last data buffer - this
// can also happen to be empty).
//  - skip_bytes, when the consumer has consumed all the input given to it
// and wants to skip before processing the next chunk
//
// For backward compatibility reasons, we also support the deprecated return value
// of type "unconsumed remainder" which can be
//  - empty optional, if the consumer consumed all the input given to it
// and is ready for more
//  - non-empty optional, when the consumer is done (and in that case
// the value is the unconsumed part of the last data buffer - this
// can also happen to be empty).

template <typename Consumer, typename CharType>
concept bool InputStreamConsumer = requires (Consumer c) {
    { c(temporary_buffer<CharType>{}) } -> future<consumption_result<CharType>>;
};

template <typename Consumer, typename CharType>
concept bool ObsoleteInputStreamConsumer = requires (Consumer c) {
    { c(temporary_buffer<CharType>{}) } -> future<compat::optional<temporary_buffer<CharType>>>;
};
)

template <typename CharType>
class input_stream final {
    static_assert(sizeof(CharType) == 1, "must buffer stream of bytes");
    data_source _fd;
    temporary_buffer<CharType> _buf;
    bool _eof = false;
private:
    using tmp_buf = temporary_buffer<CharType>;
    size_t available() const { return _buf.size(); }
protected:
    void reset() { _buf = {}; }
    data_source* fd() { return &_fd; }
public:
    using consumption_result_type = consumption_result<CharType>;
    // unconsumed_remainder is mapped for compatibility only; new code should use consumption_result_type
    using unconsumed_remainder = compat::optional<tmp_buf>;
    using char_type = CharType;
    input_stream() = default;
    explicit input_stream(data_source fd) : _fd(std::move(fd)), _buf(0) {}
    input_stream(input_stream&&) = default;
    input_stream& operator=(input_stream&&) = default;
    future<temporary_buffer<CharType>> read_exactly(size_t n);
    template <typename Consumer>
    GCC6_CONCEPT(requires InputStreamConsumer<Consumer, CharType> || ObsoleteInputStreamConsumer<Consumer, CharType>)
    future<> consume(Consumer&& c);
    template <typename Consumer>
    GCC6_CONCEPT(requires InputStreamConsumer<Consumer, CharType> || ObsoleteInputStreamConsumer<Consumer, CharType>)
    future<> consume(Consumer& c);
    bool eof() { return _eof; }
    /// Returns some data from the stream, or an empty buffer on end of
    /// stream.
    future<tmp_buf> read();
    /// Returns up to n bytes from the stream, or an empty buffer on end of
    /// stream.
    future<tmp_buf> read_up_to(size_t n);
    /// Detaches the \c input_stream from the underlying data source.
    ///
    /// Waits for any background operations (for example, read-ahead) to
    /// complete, so that the any resources the stream is using can be
    /// safely destroyed.  An example is a \ref file resource used by
    /// the stream returned by make_file_input_stream().
    ///
    /// \return a future that becomes ready when this stream no longer
    ///         needs the data source.
    future<> close() {
        return _fd.close();
    }
    /// Ignores n next bytes from the stream.
    future<> skip(uint64_t n);

    /// Detaches the underlying \c data_source from the \c input_stream.
    ///
    /// The intended usage is custom \c data_source_impl implementations
    /// wrapping an existing \c input_stream, therefore it shouldn't be
    /// called on an \c input_stream that was already used.
    /// After calling \c detach() the \c input_stream is in an unusable,
    /// moved-from state.
    ///
    /// \throws std::logic_error if called on a used stream
    ///
    /// \returns the data_source
    data_source detach() &&;
private:
    future<temporary_buffer<CharType>> read_exactly_part(size_t n, tmp_buf buf, size_t completed);
};

// Facilitates data buffering before it's handed over to data_sink.
//
// When trim_to_size is true it's guaranteed that data sink will not receive
// chunks larger than the configured size, which could be the case when a
// single write call is made with data larger than the configured size.
//
// The data sink will not receive empty chunks.
//
// \note All methods must be called sequentially.  That is, no method
// may be invoked before the previous method's returned future is
// resolved.
template <typename CharType>
class output_stream final {
    static_assert(sizeof(CharType) == 1, "must buffer stream of bytes");
    data_sink _fd;
    temporary_buffer<CharType> _buf;
    net::packet _zc_bufs = net::packet::make_null_packet(); //zero copy buffers
    size_t _size = 0;
    size_t _begin = 0;
    size_t _end = 0;
    bool _trim_to_size = false;
    bool _batch_flushes = false;
    compat::optional<promise<>> _in_batch;
    bool _flush = false;
    bool _flushing = false;
    std::exception_ptr _ex;
private:
    size_t available() const { return _end - _begin; }
    size_t possibly_available() const { return _size - _begin; }
    future<> split_and_put(temporary_buffer<CharType> buf);
    future<> put(temporary_buffer<CharType> buf);
    void poll_flush();
    future<> zero_copy_put(net::packet p);
    future<> zero_copy_split_and_put(net::packet p);
    [[gnu::noinline]]
    future<> slow_write(const CharType* buf, size_t n);
public:
    using char_type = CharType;
    output_stream() = default;
    output_stream(data_sink fd, size_t size, bool trim_to_size = false, bool batch_flushes = false)
        : _fd(std::move(fd)), _size(size), _trim_to_size(trim_to_size), _batch_flushes(batch_flushes) {}
    output_stream(output_stream&&) = default;
    output_stream& operator=(output_stream&&) = default;
    ~output_stream() { assert(!_in_batch && "Was this stream properly closed?"); }
    future<> write(const char_type* buf, size_t n);
    future<> write(const char_type* buf);

    template <typename StringChar, typename SizeType, SizeType MaxSize, bool NulTerminate>
    future<> write(const basic_sstring<StringChar, SizeType, MaxSize, NulTerminate>& s);
    future<> write(const std::basic_string<char_type>& s);

    future<> write(net::packet p);
    future<> write(scattered_message<char_type> msg);
    future<> write(temporary_buffer<char_type>);
    future<> flush();

    /// Flushes the stream before closing it (and the underlying data sink) to
    /// any further writes.  The resulting future must be waited on before
    /// destroying this object.
    future<> close();

    /// Detaches the underlying \c data_sink from the \c output_stream.
    ///
    /// The intended usage is custom \c data_sink_impl implementations
    /// wrapping an existing \c output_stream, therefore it shouldn't be
    /// called on an \c output_stream that was already used.
    /// After calling \c detach() the \c output_stream is in an unusable,
    /// moved-from state.
    ///
    /// \throws std::logic_error if called on a used stream
    ///
    /// \returns the data_sink
    data_sink detach() &&;
private:
    friend class reactor;
};

/*!
 * \brief copy all the content from the input stream to the output stream
 */
template <typename CharType>
future<> copy(input_stream<CharType>&, output_stream<CharType>&);

}

#include "iostream-impl.hh"
<commit_msg>iostream: Constify eof() function<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

//
// Buffered input and output streams
//
// Two abstract classes (data_source and data_sink) provide means
// to acquire bulk data from, or push bulk data to, some provider.
// These could be tied to a TCP connection, a disk file, or a memory
// buffer.
//
// Two concrete classes (input_stream and output_stream) buffer data
// from data_source and data_sink and provide easier means to process
// it.
//

#pragma once

#include <seastar/core/future.hh>
#include <seastar/core/temporary_buffer.hh>
#include <seastar/core/scattered_message.hh>
#include <seastar/util/std-compat.hh>

namespace seastar {

namespace net { class packet; }

class data_source_impl {
public:
    virtual ~data_source_impl() {}
    virtual future<temporary_buffer<char>> get() = 0;
    virtual future<temporary_buffer<char>> skip(uint64_t n);
    virtual future<> close() { return make_ready_future<>(); }
};

class data_source {
    std::unique_ptr<data_source_impl> _dsi;
protected:
    data_source_impl* impl() const { return _dsi.get(); }
public:
    data_source() = default;
    explicit data_source(std::unique_ptr<data_source_impl> dsi) : _dsi(std::move(dsi)) {}
    data_source(data_source&& x) = default;
    data_source& operator=(data_source&& x) = default;
    future<temporary_buffer<char>> get() { return _dsi->get(); }
    future<temporary_buffer<char>> skip(uint64_t n) { return _dsi->skip(n); }
    future<> close() { return _dsi->close(); }
};

class data_sink_impl {
public:
    virtual ~data_sink_impl() {}
    virtual temporary_buffer<char> allocate_buffer(size_t size) {
        return temporary_buffer<char>(size);
    }
    virtual future<> put(net::packet data) = 0;
    virtual future<> put(std::vector<temporary_buffer<char>> data) {
        net::packet p;
        p.reserve(data.size());
        for (auto& buf : data) {
            p = net::packet(std::move(p), net::fragment{buf.get_write(), buf.size()}, buf.release());
        }
        return put(std::move(p));
    }
    virtual future<> put(temporary_buffer<char> buf) {
        return put(net::packet(net::fragment{buf.get_write(), buf.size()}, buf.release()));
    }
    virtual future<> flush() {
        return make_ready_future<>();
    }
    virtual future<> close() = 0;
};

class data_sink {
    std::unique_ptr<data_sink_impl> _dsi;
public:
    data_sink() = default;
    explicit data_sink(std::unique_ptr<data_sink_impl> dsi) : _dsi(std::move(dsi)) {}
    data_sink(data_sink&& x) = default;
    data_sink& operator=(data_sink&& x) = default;
    temporary_buffer<char> allocate_buffer(size_t size) {
        return _dsi->allocate_buffer(size);
    }
    future<> put(std::vector<temporary_buffer<char>> data) {
        return _dsi->put(std::move(data));
    }
    future<> put(temporary_buffer<char> data) {
        return _dsi->put(std::move(data));
    }
    future<> put(net::packet p) {
        return _dsi->put(std::move(p));
    }
    future<> flush() {
        return _dsi->flush();
    }
    future<> close() { return _dsi->close(); }
};

struct continue_consuming {};

template <typename CharType>
class stop_consuming {
public:
    using tmp_buf = temporary_buffer<CharType>;
    explicit stop_consuming(tmp_buf buf) : _buf(std::move(buf)) {}

    tmp_buf& get_buffer() { return _buf; }
    const tmp_buf& get_buffer() const { return _buf; }
private:
    tmp_buf _buf;
};

class skip_bytes {
public:
    explicit skip_bytes(uint64_t v) : _value(v) {}
    uint64_t get_value() const { return _value; }
private:
    uint64_t _value;
};

template <typename CharType>
class consumption_result {
public:
    using stop_consuming_type = stop_consuming<CharType>;
    using consumption_variant = compat::variant<continue_consuming, stop_consuming_type, skip_bytes>;
    using tmp_buf = typename stop_consuming_type::tmp_buf;

    /*[[deprecated]]*/ consumption_result(compat::optional<tmp_buf> opt_buf) {
        if (opt_buf) {
            _result = stop_consuming_type{std::move(opt_buf.value())};
        }
    }

    consumption_result(const continue_consuming&) {}
    consumption_result(stop_consuming_type&& stop) : _result(std::move(stop)) {}
    consumption_result(skip_bytes&& skip) : _result(std::move(skip)) {}

    consumption_variant& get() { return _result; }
    const consumption_variant& get() const { return _result; }

private:
    consumption_variant _result;
};

// Consumer concept, for consume() method
GCC6_CONCEPT(
// The consumer should operate on the data given to it, and
// return a future "consumption result", which can be
//  - continue_consuming, if the consumer has consumed all the input given
// to it and is ready for more
//  - stop_consuming, when the consumer is done (and in that case
// the contained buffer is the unconsumed part of the last data buffer - this
// can also happen to be empty).
//  - skip_bytes, when the consumer has consumed all the input given to it
// and wants to skip before processing the next chunk
//
// For backward compatibility reasons, we also support the deprecated return value
// of type "unconsumed remainder" which can be
//  - empty optional, if the consumer consumed all the input given to it
// and is ready for more
//  - non-empty optional, when the consumer is done (and in that case
// the value is the unconsumed part of the last data buffer - this
// can also happen to be empty).

template <typename Consumer, typename CharType>
concept bool InputStreamConsumer = requires (Consumer c) {
    { c(temporary_buffer<CharType>{}) } -> future<consumption_result<CharType>>;
};

template <typename Consumer, typename CharType>
concept bool ObsoleteInputStreamConsumer = requires (Consumer c) {
    { c(temporary_buffer<CharType>{}) } -> future<compat::optional<temporary_buffer<CharType>>>;
};
)

template <typename CharType>
class input_stream final {
    static_assert(sizeof(CharType) == 1, "must buffer stream of bytes");
    data_source _fd;
    temporary_buffer<CharType> _buf;
    bool _eof = false;
private:
    using tmp_buf = temporary_buffer<CharType>;
    size_t available() const { return _buf.size(); }
protected:
    void reset() { _buf = {}; }
    data_source* fd() { return &_fd; }
public:
    using consumption_result_type = consumption_result<CharType>;
    // unconsumed_remainder is mapped for compatibility only; new code should use consumption_result_type
    using unconsumed_remainder = compat::optional<tmp_buf>;
    using char_type = CharType;
    input_stream() = default;
    explicit input_stream(data_source fd) : _fd(std::move(fd)), _buf(0) {}
    input_stream(input_stream&&) = default;
    input_stream& operator=(input_stream&&) = default;
    future<temporary_buffer<CharType>> read_exactly(size_t n);
    template <typename Consumer>
    GCC6_CONCEPT(requires InputStreamConsumer<Consumer, CharType> || ObsoleteInputStreamConsumer<Consumer, CharType>)
    future<> consume(Consumer&& c);
    template <typename Consumer>
    GCC6_CONCEPT(requires InputStreamConsumer<Consumer, CharType> || ObsoleteInputStreamConsumer<Consumer, CharType>)
    future<> consume(Consumer& c);
    bool eof() const { return _eof; }
    /// Returns some data from the stream, or an empty buffer on end of
    /// stream.
    future<tmp_buf> read();
    /// Returns up to n bytes from the stream, or an empty buffer on end of
    /// stream.
    future<tmp_buf> read_up_to(size_t n);
    /// Detaches the \c input_stream from the underlying data source.
    ///
    /// Waits for any background operations (for example, read-ahead) to
    /// complete, so that the any resources the stream is using can be
    /// safely destroyed.  An example is a \ref file resource used by
    /// the stream returned by make_file_input_stream().
    ///
    /// \return a future that becomes ready when this stream no longer
    ///         needs the data source.
    future<> close() {
        return _fd.close();
    }
    /// Ignores n next bytes from the stream.
    future<> skip(uint64_t n);

    /// Detaches the underlying \c data_source from the \c input_stream.
    ///
    /// The intended usage is custom \c data_source_impl implementations
    /// wrapping an existing \c input_stream, therefore it shouldn't be
    /// called on an \c input_stream that was already used.
    /// After calling \c detach() the \c input_stream is in an unusable,
    /// moved-from state.
    ///
    /// \throws std::logic_error if called on a used stream
    ///
    /// \returns the data_source
    data_source detach() &&;
private:
    future<temporary_buffer<CharType>> read_exactly_part(size_t n, tmp_buf buf, size_t completed);
};

// Facilitates data buffering before it's handed over to data_sink.
//
// When trim_to_size is true it's guaranteed that data sink will not receive
// chunks larger than the configured size, which could be the case when a
// single write call is made with data larger than the configured size.
//
// The data sink will not receive empty chunks.
//
// \note All methods must be called sequentially.  That is, no method
// may be invoked before the previous method's returned future is
// resolved.
template <typename CharType>
class output_stream final {
    static_assert(sizeof(CharType) == 1, "must buffer stream of bytes");
    data_sink _fd;
    temporary_buffer<CharType> _buf;
    net::packet _zc_bufs = net::packet::make_null_packet(); //zero copy buffers
    size_t _size = 0;
    size_t _begin = 0;
    size_t _end = 0;
    bool _trim_to_size = false;
    bool _batch_flushes = false;
    compat::optional<promise<>> _in_batch;
    bool _flush = false;
    bool _flushing = false;
    std::exception_ptr _ex;
private:
    size_t available() const { return _end - _begin; }
    size_t possibly_available() const { return _size - _begin; }
    future<> split_and_put(temporary_buffer<CharType> buf);
    future<> put(temporary_buffer<CharType> buf);
    void poll_flush();
    future<> zero_copy_put(net::packet p);
    future<> zero_copy_split_and_put(net::packet p);
    [[gnu::noinline]]
    future<> slow_write(const CharType* buf, size_t n);
public:
    using char_type = CharType;
    output_stream() = default;
    output_stream(data_sink fd, size_t size, bool trim_to_size = false, bool batch_flushes = false)
        : _fd(std::move(fd)), _size(size), _trim_to_size(trim_to_size), _batch_flushes(batch_flushes) {}
    output_stream(output_stream&&) = default;
    output_stream& operator=(output_stream&&) = default;
    ~output_stream() { assert(!_in_batch && "Was this stream properly closed?"); }
    future<> write(const char_type* buf, size_t n);
    future<> write(const char_type* buf);

    template <typename StringChar, typename SizeType, SizeType MaxSize, bool NulTerminate>
    future<> write(const basic_sstring<StringChar, SizeType, MaxSize, NulTerminate>& s);
    future<> write(const std::basic_string<char_type>& s);

    future<> write(net::packet p);
    future<> write(scattered_message<char_type> msg);
    future<> write(temporary_buffer<char_type>);
    future<> flush();

    /// Flushes the stream before closing it (and the underlying data sink) to
    /// any further writes.  The resulting future must be waited on before
    /// destroying this object.
    future<> close();

    /// Detaches the underlying \c data_sink from the \c output_stream.
    ///
    /// The intended usage is custom \c data_sink_impl implementations
    /// wrapping an existing \c output_stream, therefore it shouldn't be
    /// called on an \c output_stream that was already used.
    /// After calling \c detach() the \c output_stream is in an unusable,
    /// moved-from state.
    ///
    /// \throws std::logic_error if called on a used stream
    ///
    /// \returns the data_sink
    data_sink detach() &&;
private:
    friend class reactor;
};

/*!
 * \brief copy all the content from the input stream to the output stream
 */
template <typename CharType>
future<> copy(input_stream<CharType>&, output_stream<CharType>&);

}

#include "iostream-impl.hh"
<|endoftext|>


<commit_before>//===- ScalarReplAggregates.cpp - Scalar Replacement of Aggregates --------===//
//
// This transformation implements the well known scalar replacement of
// aggregates transformation.  This xform breaks up alloca instructions of
// aggregate type (structure or array) into individual alloca instructions for
// each member (if possible).  Then, if possible, it transforms the individual
// alloca instructions into nice clean scalar SSA form.
//
// This combines a simple SRoA algorithm with the Mem2Reg algorithm because
// often interact, especially for C++ programs.  As such, iterating between
// SRoA, then Mem2Reg until we run out of things to promote works well.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Pass.h"
#include "llvm/iMemory.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
#include "Support/StringExtras.h"

namespace {
  Statistic<> NumReplaced("scalarrepl", "Number of alloca's broken up");
  Statistic<> NumPromoted("scalarrepl", "Number of alloca's promoted");

  struct SROA : public FunctionPass {
    bool runOnFunction(Function &F);

    bool performScalarRepl(Function &F);
    bool performPromotion(Function &F);

    // getAnalysisUsage - This pass does not require any passes, but we know it
    // will not alter the CFG, so say so.
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<DominanceFrontier>();
      AU.addRequired<TargetData>();
      AU.setPreservesCFG();
    }

  private:
    bool isSafeElementUse(Value *Ptr);
    bool isSafeUseOfAllocation(Instruction *User);
    bool isSafeStructAllocaToPromote(AllocationInst *AI);
    bool isSafeArrayAllocaToPromote(AllocationInst *AI);
    AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocationInst *Base);
  };

  RegisterOpt<SROA> X("scalarrepl", "Scalar Replacement of Aggregates");
}

Pass *createScalarReplAggregatesPass() { return new SROA(); }

bool SROA::runOnFunction(Function &F) {
  bool Changed = false, LocalChange;
  do {
    LocalChange = performScalarRepl(F);
    LocalChange |= performPromotion(F);
    Changed |= LocalChange;
  } while (LocalChange);

  return Changed;
}

bool SROA::performPromotion(Function &F) {
  std::vector<AllocaInst*> Allocas;
  const TargetData &TD = getAnalysis<TargetData>();

  BasicBlock &BB = F.getEntryNode();  // Get the entry node for the function

  bool Changed  = false;

  while (1) {
    Allocas.clear();

    // Find allocas that are safe to promote, by looking at all instructions in
    // the entry node
    for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I)
      if (AllocaInst *AI = dyn_cast<AllocaInst>(I))       // Is it an alloca?
        if (isAllocaPromotable(AI, TD))
          Allocas.push_back(AI);

    if (Allocas.empty()) break;

    PromoteMemToReg(Allocas, getAnalysis<DominanceFrontier>(), TD);
    NumPromoted += Allocas.size();
    Changed = true;
  }

  return Changed;
}

// performScalarRepl - This algorithm is a simple worklist driven algorithm,
// which runs on all of the malloc/alloca instructions in the function, removing
// them if they are only used by getelementptr instructions.
//
bool SROA::performScalarRepl(Function &F) {
  std::vector<AllocationInst*> WorkList;

  // Scan the entry basic block, adding any alloca's and mallocs to the worklist
  BasicBlock &BB = F.getEntryNode();
  for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
    if (AllocationInst *A = dyn_cast<AllocationInst>(I))
      WorkList.push_back(A);

  // Process the worklist
  bool Changed = false;
  while (!WorkList.empty()) {
    AllocationInst *AI = WorkList.back();
    WorkList.pop_back();

    // We cannot transform the allocation instruction if it is an array
    // allocation (allocations OF arrays are ok though), and an allocation of a
    // scalar value cannot be decomposed at all.
    //
    if (AI->isArrayAllocation() ||
        (!isa<StructType>(AI->getAllocatedType()) &&
         !isa<ArrayType>(AI->getAllocatedType()))) continue;

    // Check that all of the users of the allocation are capable of being
    // transformed.
    if (isa<StructType>(AI->getAllocatedType())) {
      if (!isSafeStructAllocaToPromote(AI))
        continue;
    } else if (!isSafeArrayAllocaToPromote(AI))
      continue;

    DEBUG(std::cerr << "Found inst to xform: " << *AI);
    Changed = true;

    std::vector<AllocaInst*> ElementAllocas;
    if (const StructType *ST = dyn_cast<StructType>(AI->getAllocatedType())) {
      ElementAllocas.reserve(ST->getNumContainedTypes());
      for (unsigned i = 0, e = ST->getNumContainedTypes(); i != e; ++i) {
        AllocaInst *NA = new AllocaInst(ST->getContainedType(i), 0,
                                        AI->getName() + "." + utostr(i), AI);
        ElementAllocas.push_back(NA);
        WorkList.push_back(NA);  // Add to worklist for recursive processing
      }
    } else {
      const ArrayType *AT = cast<ArrayType>(AI->getAllocatedType());
      ElementAllocas.reserve(AT->getNumElements());
      const Type *ElTy = AT->getElementType();
      for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) {
        AllocaInst *NA = new AllocaInst(ElTy, 0,
                                        AI->getName() + "." + utostr(i), AI);
        ElementAllocas.push_back(NA);
        WorkList.push_back(NA);  // Add to worklist for recursive processing
      }
    }

    // Now that we have created the alloca instructions that we want to use,
    // expand the getelementptr instructions to use them.
    //
    for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
         I != E; ++I) {
      Instruction *User = cast<Instruction>(*I);
      if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {
        // We now know that the GEP is of the form: GEP <ptr>, 0, <cst>
        uint64_t Idx = cast<ConstantInt>(GEPI->getOperand(2))->getRawValue();

        assert(Idx < ElementAllocas.size() && "Index out of range?");
        AllocaInst *AllocaToUse = ElementAllocas[Idx];

        Value *RepValue;
        if (GEPI->getNumOperands() == 3) {
          // Do not insert a new getelementptr instruction with zero indices,
          // only to have it optimized out later.
          RepValue = AllocaToUse;
        } else {
          // We are indexing deeply into the structure, so we still need a
          // getelement ptr instruction to finish the indexing.  This may be
          // expanded itself once the worklist is rerun.
          //
          std::string OldName = GEPI->getName();  // Steal the old name...
          std::vector<Value*> NewArgs;
          NewArgs.push_back(Constant::getNullValue(Type::LongTy));
          NewArgs.insert(NewArgs.end(), GEPI->op_begin()+3, GEPI->op_end());
          GEPI->setName("");
          RepValue =
            new GetElementPtrInst(AllocaToUse, NewArgs, OldName, GEPI);
        }

        // Move all of the users over to the new GEP.
        GEPI->replaceAllUsesWith(RepValue);
        // Delete the old GEP
        GEPI->getParent()->getInstList().erase(GEPI);
      } else {
        assert(0 && "Unexpected instruction type!");
      }
    }

    // Finally, delete the Alloca instruction
    AI->getParent()->getInstList().erase(AI);
    NumReplaced++;
  }

  return Changed;
}

/// isSafeUseOfAllocation - Check to see if this user is an allowed use for an
/// aggregate allocation.
///
bool SROA::isSafeUseOfAllocation(Instruction *User) {
  if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {
    // The GEP is safe to transform if it is of the form GEP <ptr>, 0, <cst>
    if (GEPI->getNumOperands() <= 2 ||
        GEPI->getOperand(1) != Constant::getNullValue(Type::LongTy) ||
        !isa<Constant>(GEPI->getOperand(2)) ||
        isa<ConstantExpr>(GEPI->getOperand(2)))
      return false;
  } else {
    return false;
  }
  return true;
}

/// isSafeElementUse - Check to see if this use is an allowed use for a
/// getelementptr instruction of an array aggregate allocation.
///
bool SROA::isSafeElementUse(Value *Ptr) {
  for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end();
       I != E; ++I) {
    Instruction *User = cast<Instruction>(*I);
    switch (User->getOpcode()) {
    case Instruction::Load:  return true;
    case Instruction::Store: return User->getOperand(0) != Ptr;
    case Instruction::GetElementPtr: {
      GetElementPtrInst *GEP = cast<GetElementPtrInst>(User);
      if (GEP->getNumOperands() > 1) {
        if (!isa<Constant>(GEP->getOperand(1)) ||
            !cast<Constant>(GEP->getOperand(1))->isNullValue())
          return false;  // Using pointer arithmetic to navigate the array...
      }
      return isSafeElementUse(GEP);
    }
    default:
      DEBUG(std::cerr << "  Transformation preventing inst: " << *User);
      return false;
    }
  }
  return true;  // All users look ok :)
}

/// isSafeStructAllocaToPromote - Check to see if the specified allocation of a
/// structure can be broken down into elements.
///
bool SROA::isSafeStructAllocaToPromote(AllocationInst *AI) {
  // Loop over the use list of the alloca.  We can only transform it if all of
  // the users are safe to transform.
  //
  for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
       I != E; ++I) {
    if (!isSafeUseOfAllocation(cast<Instruction>(*I))) {
      DEBUG(std::cerr << "Cannot transform: " << *AI << "  due to user: "
                      << *I);
      return false;
    }

    // Pedantic check to avoid breaking broken programs...
    if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*I))
      if (GEPI->getNumOperands() == 3 && !isSafeElementUse(GEPI))
        return false;
  }
  return true;
}

/// isSafeArrayAllocaToPromote - Check to see if the specified allocation of a
/// structure can be broken down into elements.
///
bool SROA::isSafeArrayAllocaToPromote(AllocationInst *AI) {
  const ArrayType *AT = cast<ArrayType>(AI->getAllocatedType());
  int64_t NumElements = AT->getNumElements();

  // Loop over the use list of the alloca.  We can only transform it if all of
  // the users are safe to transform.  Array allocas have extra constraints to
  // meet though.
  //
  for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
       I != E; ++I) {
    Instruction *User = cast<Instruction>(*I);
    if (!isSafeUseOfAllocation(User)) {
      DEBUG(std::cerr << "Cannot transform: " << *AI << "  due to user: "
                      << User);
      return false;
    }

    // Check to make sure that getelementptr follow the extra rules for arrays:
    if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {
      // Check to make sure that index falls within the array.  If not,
      // something funny is going on, so we won't do the optimization.
      //
      if (cast<ConstantSInt>(GEPI->getOperand(2))->getValue() >= NumElements)
        return false;

      // Check to make sure that the only thing that uses the resultant pointer
      // is safe for an array access.  For example, code that looks like:
      //   P = &A[0];  P = P + 1
      // is legal, and should prevent promotion.
      //
      if (!isSafeElementUse(GEPI)) {
        DEBUG(std::cerr << "Cannot transform: " << *AI
                        << "  due to uses of user: " << *GEPI);
        return false;
      }
    }
  }
  return true;
}

<commit_msg>Apostrophes are only used for possession and quoting.<commit_after>//===- ScalarReplAggregates.cpp - Scalar Replacement of Aggregates --------===//
//
// This transformation implements the well known scalar replacement of
// aggregates transformation.  This xform breaks up alloca instructions of
// aggregate type (structure or array) into individual alloca instructions for
// each member (if possible).  Then, if possible, it transforms the individual
// alloca instructions into nice clean scalar SSA form.
//
// This combines a simple SRoA algorithm with the Mem2Reg algorithm because
// often interact, especially for C++ programs.  As such, iterating between
// SRoA, then Mem2Reg until we run out of things to promote works well.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Pass.h"
#include "llvm/iMemory.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
#include "Support/StringExtras.h"

namespace {
  Statistic<> NumReplaced("scalarrepl", "Number of allocas broken up");
  Statistic<> NumPromoted("scalarrepl", "Number of allocas promoted");

  struct SROA : public FunctionPass {
    bool runOnFunction(Function &F);

    bool performScalarRepl(Function &F);
    bool performPromotion(Function &F);

    // getAnalysisUsage - This pass does not require any passes, but we know it
    // will not alter the CFG, so say so.
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<DominanceFrontier>();
      AU.addRequired<TargetData>();
      AU.setPreservesCFG();
    }

  private:
    bool isSafeElementUse(Value *Ptr);
    bool isSafeUseOfAllocation(Instruction *User);
    bool isSafeStructAllocaToPromote(AllocationInst *AI);
    bool isSafeArrayAllocaToPromote(AllocationInst *AI);
    AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocationInst *Base);
  };

  RegisterOpt<SROA> X("scalarrepl", "Scalar Replacement of Aggregates");
}

Pass *createScalarReplAggregatesPass() { return new SROA(); }

bool SROA::runOnFunction(Function &F) {
  bool Changed = false, LocalChange;
  do {
    LocalChange = performScalarRepl(F);
    LocalChange |= performPromotion(F);
    Changed |= LocalChange;
  } while (LocalChange);

  return Changed;
}

bool SROA::performPromotion(Function &F) {
  std::vector<AllocaInst*> Allocas;
  const TargetData &TD = getAnalysis<TargetData>();

  BasicBlock &BB = F.getEntryNode();  // Get the entry node for the function

  bool Changed  = false;

  while (1) {
    Allocas.clear();

    // Find allocas that are safe to promote, by looking at all instructions in
    // the entry node
    for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I)
      if (AllocaInst *AI = dyn_cast<AllocaInst>(I))       // Is it an alloca?
        if (isAllocaPromotable(AI, TD))
          Allocas.push_back(AI);

    if (Allocas.empty()) break;

    PromoteMemToReg(Allocas, getAnalysis<DominanceFrontier>(), TD);
    NumPromoted += Allocas.size();
    Changed = true;
  }

  return Changed;
}

// performScalarRepl - This algorithm is a simple worklist driven algorithm,
// which runs on all of the malloc/alloca instructions in the function, removing
// them if they are only used by getelementptr instructions.
//
bool SROA::performScalarRepl(Function &F) {
  std::vector<AllocationInst*> WorkList;

  // Scan the entry basic block, adding any alloca's and mallocs to the worklist
  BasicBlock &BB = F.getEntryNode();
  for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
    if (AllocationInst *A = dyn_cast<AllocationInst>(I))
      WorkList.push_back(A);

  // Process the worklist
  bool Changed = false;
  while (!WorkList.empty()) {
    AllocationInst *AI = WorkList.back();
    WorkList.pop_back();

    // We cannot transform the allocation instruction if it is an array
    // allocation (allocations OF arrays are ok though), and an allocation of a
    // scalar value cannot be decomposed at all.
    //
    if (AI->isArrayAllocation() ||
        (!isa<StructType>(AI->getAllocatedType()) &&
         !isa<ArrayType>(AI->getAllocatedType()))) continue;

    // Check that all of the users of the allocation are capable of being
    // transformed.
    if (isa<StructType>(AI->getAllocatedType())) {
      if (!isSafeStructAllocaToPromote(AI))
        continue;
    } else if (!isSafeArrayAllocaToPromote(AI))
      continue;

    DEBUG(std::cerr << "Found inst to xform: " << *AI);
    Changed = true;

    std::vector<AllocaInst*> ElementAllocas;
    if (const StructType *ST = dyn_cast<StructType>(AI->getAllocatedType())) {
      ElementAllocas.reserve(ST->getNumContainedTypes());
      for (unsigned i = 0, e = ST->getNumContainedTypes(); i != e; ++i) {
        AllocaInst *NA = new AllocaInst(ST->getContainedType(i), 0,
                                        AI->getName() + "." + utostr(i), AI);
        ElementAllocas.push_back(NA);
        WorkList.push_back(NA);  // Add to worklist for recursive processing
      }
    } else {
      const ArrayType *AT = cast<ArrayType>(AI->getAllocatedType());
      ElementAllocas.reserve(AT->getNumElements());
      const Type *ElTy = AT->getElementType();
      for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) {
        AllocaInst *NA = new AllocaInst(ElTy, 0,
                                        AI->getName() + "." + utostr(i), AI);
        ElementAllocas.push_back(NA);
        WorkList.push_back(NA);  // Add to worklist for recursive processing
      }
    }

    // Now that we have created the alloca instructions that we want to use,
    // expand the getelementptr instructions to use them.
    //
    for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
         I != E; ++I) {
      Instruction *User = cast<Instruction>(*I);
      if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {
        // We now know that the GEP is of the form: GEP <ptr>, 0, <cst>
        uint64_t Idx = cast<ConstantInt>(GEPI->getOperand(2))->getRawValue();

        assert(Idx < ElementAllocas.size() && "Index out of range?");
        AllocaInst *AllocaToUse = ElementAllocas[Idx];

        Value *RepValue;
        if (GEPI->getNumOperands() == 3) {
          // Do not insert a new getelementptr instruction with zero indices,
          // only to have it optimized out later.
          RepValue = AllocaToUse;
        } else {
          // We are indexing deeply into the structure, so we still need a
          // getelement ptr instruction to finish the indexing.  This may be
          // expanded itself once the worklist is rerun.
          //
          std::string OldName = GEPI->getName();  // Steal the old name...
          std::vector<Value*> NewArgs;
          NewArgs.push_back(Constant::getNullValue(Type::LongTy));
          NewArgs.insert(NewArgs.end(), GEPI->op_begin()+3, GEPI->op_end());
          GEPI->setName("");
          RepValue =
            new GetElementPtrInst(AllocaToUse, NewArgs, OldName, GEPI);
        }

        // Move all of the users over to the new GEP.
        GEPI->replaceAllUsesWith(RepValue);
        // Delete the old GEP
        GEPI->getParent()->getInstList().erase(GEPI);
      } else {
        assert(0 && "Unexpected instruction type!");
      }
    }

    // Finally, delete the Alloca instruction
    AI->getParent()->getInstList().erase(AI);
    NumReplaced++;
  }

  return Changed;
}

/// isSafeUseOfAllocation - Check to see if this user is an allowed use for an
/// aggregate allocation.
///
bool SROA::isSafeUseOfAllocation(Instruction *User) {
  if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {
    // The GEP is safe to transform if it is of the form GEP <ptr>, 0, <cst>
    if (GEPI->getNumOperands() <= 2 ||
        GEPI->getOperand(1) != Constant::getNullValue(Type::LongTy) ||
        !isa<Constant>(GEPI->getOperand(2)) ||
        isa<ConstantExpr>(GEPI->getOperand(2)))
      return false;
  } else {
    return false;
  }
  return true;
}

/// isSafeElementUse - Check to see if this use is an allowed use for a
/// getelementptr instruction of an array aggregate allocation.
///
bool SROA::isSafeElementUse(Value *Ptr) {
  for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end();
       I != E; ++I) {
    Instruction *User = cast<Instruction>(*I);
    switch (User->getOpcode()) {
    case Instruction::Load:  return true;
    case Instruction::Store: return User->getOperand(0) != Ptr;
    case Instruction::GetElementPtr: {
      GetElementPtrInst *GEP = cast<GetElementPtrInst>(User);
      if (GEP->getNumOperands() > 1) {
        if (!isa<Constant>(GEP->getOperand(1)) ||
            !cast<Constant>(GEP->getOperand(1))->isNullValue())
          return false;  // Using pointer arithmetic to navigate the array...
      }
      return isSafeElementUse(GEP);
    }
    default:
      DEBUG(std::cerr << "  Transformation preventing inst: " << *User);
      return false;
    }
  }
  return true;  // All users look ok :)
}

/// isSafeStructAllocaToPromote - Check to see if the specified allocation of a
/// structure can be broken down into elements.
///
bool SROA::isSafeStructAllocaToPromote(AllocationInst *AI) {
  // Loop over the use list of the alloca.  We can only transform it if all of
  // the users are safe to transform.
  //
  for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
       I != E; ++I) {
    if (!isSafeUseOfAllocation(cast<Instruction>(*I))) {
      DEBUG(std::cerr << "Cannot transform: " << *AI << "  due to user: "
                      << *I);
      return false;
    }

    // Pedantic check to avoid breaking broken programs...
    if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*I))
      if (GEPI->getNumOperands() == 3 && !isSafeElementUse(GEPI))
        return false;
  }
  return true;
}

/// isSafeArrayAllocaToPromote - Check to see if the specified allocation of a
/// structure can be broken down into elements.
///
bool SROA::isSafeArrayAllocaToPromote(AllocationInst *AI) {
  const ArrayType *AT = cast<ArrayType>(AI->getAllocatedType());
  int64_t NumElements = AT->getNumElements();

  // Loop over the use list of the alloca.  We can only transform it if all of
  // the users are safe to transform.  Array allocas have extra constraints to
  // meet though.
  //
  for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
       I != E; ++I) {
    Instruction *User = cast<Instruction>(*I);
    if (!isSafeUseOfAllocation(User)) {
      DEBUG(std::cerr << "Cannot transform: " << *AI << "  due to user: "
                      << User);
      return false;
    }

    // Check to make sure that getelementptr follow the extra rules for arrays:
    if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {
      // Check to make sure that index falls within the array.  If not,
      // something funny is going on, so we won't do the optimization.
      //
      if (cast<ConstantSInt>(GEPI->getOperand(2))->getValue() >= NumElements)
        return false;

      // Check to make sure that the only thing that uses the resultant pointer
      // is safe for an array access.  For example, code that looks like:
      //   P = &A[0];  P = P + 1
      // is legal, and should prevent promotion.
      //
      if (!isSafeElementUse(GEPI)) {
        DEBUG(std::cerr << "Cannot transform: " << *AI
                        << "  due to uses of user: " << *GEPI);
        return false;
      }
    }
  }
  return true;
}

<|endoftext|>


<commit_before>#ifndef SG_PLATFORM_HPP_INCLUDED
#define SG_PLATFORM_HPP_INCLUDED

#include <cstdlib>
#include <string>

#ifdef _WIN32
#define SG_INLINE __forceinline
#else
#define SG_INLINE __attribute__((always_inline))
#endif

std::string sg_getenv(const char *env) {
#ifdef _WIN32
    char *buf;
    size_t len;
    errno_t err = _dupenv_s(&buf, &len, env);
    if (err || buf == NULL)
        return "";
    std::string ret(buf);
    free(buf);
    return ret;
#else
    const char *ret = getenv(env);
    return ret ? ret : "";
#endif
}

#endif // SG_PLATFORM_HPP_INCLUDED
<commit_msg>Added SG_TLS macro for defining thread local variables.<commit_after>#ifndef SG_PLATFORM_HPP_INCLUDED
#define SG_PLATFORM_HPP_INCLUDED

#include <cstdlib>
#include <string>

#ifdef _WIN32
#define SG_INLINE __forceinline
#else
#define SG_INLINE __attribute__((always_inline))
#endif

#if defined(_MSC_VER)
#define SG_TLS __declspec( thread )
#else
#define SG_TLS __thread
#endif

std::string sg_getenv(const char *env) {
#ifdef _WIN32
    char *buf;
    size_t len;
    errno_t err = _dupenv_s(&buf, &len, env);
    if (err || buf == NULL)
        return "";
    std::string ret(buf);
    free(buf);
    return ret;
#else
    const char *ret = getenv(env);
    return ret ? ret : "";
#endif
}

#endif // SG_PLATFORM_HPP_INCLUDED
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

#if !defined(NAMESPACESCOPE_HPP)
#define NAMESPACESCOPE_HPP

#include <util/XercesDefs.hpp>
#include <util/StringPool.hpp>

//
// NamespaceScope provides a data structure for mapping namespace prefixes
// to their URI's. The mapping accurately reflects the scoping of namespaces
// at a particular instant in time.
//

class VALIDATORS_EXPORT NamespaceScope
{
public :
    // -----------------------------------------------------------------------
    //  Class specific data types
    //
    //  These really should be private, but some of the compilers we have to
    //  support are too dumb to deal with that.
    //
    //  PrefMapElem
    //      fURIId is the id of the URI from the validator's URI map. The
    //      fPrefId is the id of the prefix from our own prefix pool. The
    //      namespace stack consists of these elements.
    //
    //  StackElem
    //      The fMapCapacity is how large fMap has grown so far. fMapCount
    //      is how many of them are valid right now.
    // -----------------------------------------------------------------------
    struct PrefMapElem
    {
        unsigned int        fPrefId;
        unsigned int        fURIId;
    };

    struct StackElem
    {
        PrefMapElem*        fMap;
        unsigned int        fMapCapacity;
        unsigned int        fMapCount;
    };

    // -----------------------------------------------------------------------
    //  Constructors and Destructor
    // -----------------------------------------------------------------------
    NamespaceScope();
    ~NamespaceScope();

    // -----------------------------------------------------------------------
    //  Stack access
    // -----------------------------------------------------------------------
    unsigned int increaseDepth();
    unsigned int decreaseDepth();

    // -----------------------------------------------------------------------
    //  Prefix map methods
    // -----------------------------------------------------------------------
    void addPrefix(const XMLCh* const prefixToAdd,
                   const unsigned int uriId);

    unsigned int getNamespaceForPrefix(const XMLCh* const prefixToMap) const;
    unsigned int getNamespaceForPrefix(const XMLCh* const prefixToMap,
                                       int depthLevel) const;

    // -----------------------------------------------------------------------
    //  Miscellaneous methods
    // -----------------------------------------------------------------------
    bool isEmpty() const;
    void reset(const unsigned int emptyId);

private :
    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    NamespaceScope(const NamespaceScope&);
    void operator=(const NamespaceScope&);

    // -----------------------------------------------------------------------
    //  Private helper methods
    // -----------------------------------------------------------------------
    void expandMap(StackElem* const toExpand);
    void expandStack();

    // -----------------------------------------------------------------------
    //  Data members
    //
    //  fEmptyNamespaceId
    //      This is the special URI id for the "" namespace, which is magic
    //      because of the xmlns="" operation.
    //
    //  fPrefixPool
    //      This is the prefix pool where prefixes are hashed and given unique
    //      ids. These ids are used to track prefixes in the element stack.
    //
    //  fStack
    //  fStackCapacity
    //  fStackTop
    //      This the stack array. Its an array of pointers to StackElem
    //      structures. The capacity is the current high water mark of the
    //      stack. The top is the current top of stack (i.e. the part of it
    //      being used.)
    // -----------------------------------------------------------------------
    unsigned int  fEmptyNamespaceId;
    unsigned int  fStackCapacity;
    unsigned int  fStackTop;
    XMLStringPool fPrefixPool;
    StackElem**   fStack;
};

// ---------------------------------------------------------------------------
//  NamespaceScope: Stack access
// ---------------------------------------------------------------------------
inline unsigned int
NamespaceScope::getNamespaceForPrefix(const XMLCh* const prefixToMap) const {

    return getNamespaceForPrefix(prefixToMap, (int)(fStackTop - 1));
}

// ---------------------------------------------------------------------------
//  NamespaceScope: Miscellaneous methods
// ---------------------------------------------------------------------------
inline bool NamespaceScope::isEmpty() const
{
    return (fStackTop == 0);
}

#endif

/**
  * End of file NameSpaceScope.hpp
  */

<commit_msg>compilation fix.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

#if !defined(NAMESPACESCOPE_HPP)
#define NAMESPACESCOPE_HPP

#include <util/XercesDefs.hpp>
#include <util/StringPool.hpp>

//
// NamespaceScope provides a data structure for mapping namespace prefixes
// to their URI's. The mapping accurately reflects the scoping of namespaces
// at a particular instant in time.
//

class VALIDATORS_EXPORT NamespaceScope
{
public :
    // -----------------------------------------------------------------------
    //  Class specific data types
    //
    //  These really should be private, but some of the compilers we have to
    //  support are too dumb to deal with that.
    //
    //  PrefMapElem
    //      fURIId is the id of the URI from the validator's URI map. The
    //      fPrefId is the id of the prefix from our own prefix pool. The
    //      namespace stack consists of these elements.
    //
    //  StackElem
    //      The fMapCapacity is how large fMap has grown so far. fMapCount
    //      is how many of them are valid right now.
    // -----------------------------------------------------------------------
    struct PrefMapElem
    {
        unsigned int        fPrefId;
        unsigned int        fURIId;
    };

    struct StackElem
    {
        PrefMapElem*        fMap;
        unsigned int        fMapCapacity;
        unsigned int        fMapCount;
    };

    // -----------------------------------------------------------------------
    //  Constructors and Destructor
    // -----------------------------------------------------------------------
    NamespaceScope();
    ~NamespaceScope();

    // -----------------------------------------------------------------------
    //  Stack access
    // -----------------------------------------------------------------------
    unsigned int increaseDepth();
    unsigned int decreaseDepth();

    // -----------------------------------------------------------------------
    //  Prefix map methods
    // -----------------------------------------------------------------------
    void addPrefix(const XMLCh* const prefixToAdd,
                   const unsigned int uriId);

    unsigned int getNamespaceForPrefix(const XMLCh* const prefixToMap) const;
    unsigned int getNamespaceForPrefix(const XMLCh* const prefixToMap,
                                       const int depthLevel) const;

    // -----------------------------------------------------------------------
    //  Miscellaneous methods
    // -----------------------------------------------------------------------
    bool isEmpty() const;
    void reset(const unsigned int emptyId);

private :
    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    NamespaceScope(const NamespaceScope&);
    void operator=(const NamespaceScope&);

    // -----------------------------------------------------------------------
    //  Private helper methods
    // -----------------------------------------------------------------------
    void expandMap(StackElem* const toExpand);
    void expandStack();

    // -----------------------------------------------------------------------
    //  Data members
    //
    //  fEmptyNamespaceId
    //      This is the special URI id for the "" namespace, which is magic
    //      because of the xmlns="" operation.
    //
    //  fPrefixPool
    //      This is the prefix pool where prefixes are hashed and given unique
    //      ids. These ids are used to track prefixes in the element stack.
    //
    //  fStack
    //  fStackCapacity
    //  fStackTop
    //      This the stack array. Its an array of pointers to StackElem
    //      structures. The capacity is the current high water mark of the
    //      stack. The top is the current top of stack (i.e. the part of it
    //      being used.)
    // -----------------------------------------------------------------------
    unsigned int  fEmptyNamespaceId;
    unsigned int  fStackCapacity;
    unsigned int  fStackTop;
    XMLStringPool fPrefixPool;
    StackElem**   fStack;
};

// ---------------------------------------------------------------------------
//  NamespaceScope: Stack access
// ---------------------------------------------------------------------------
inline unsigned int
NamespaceScope::getNamespaceForPrefix(const XMLCh* const prefixToMap) const {

    return getNamespaceForPrefix(prefixToMap, (int)(fStackTop - 1));
}

// ---------------------------------------------------------------------------
//  NamespaceScope: Miscellaneous methods
// ---------------------------------------------------------------------------
inline bool NamespaceScope::isEmpty() const
{
    return (fStackTop == 0);
}

#endif

/**
  * End of file NameSpaceScope.hpp
  */

<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

//The dlopen calls were not adding to OS X until 10.3
#ifdef __APPLE__
#include <AvailabilityMacros.h>
#if !defined(MAC_OS_X_VERSION_10_3) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3)
#define APPLE_PRE_10_3
#endif
#endif

#if defined(WIN32) && !defined(__CYGWIN__)
#include <io.h>
#include <windows.h>
#include <winbase.h>
#elif defined(__APPLE__) && defined(APPLE_PRE_10_3)
#include <mach-o/dyld.h>
#else // all other unix
#include <unistd.h>
#ifdef __hpux
// Although HP-UX has dlopen() it is broken! We therefore need to stick
// to shl_load()/shl_unload()/shl_findsym()
#include <dl.h>
#include <errno.h>
#else
#include <dlfcn.h>
#endif
#endif

#include <osg/Notify>
#include <osg/GLExtensions>

#include <osgDB/DynamicLibrary>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/ConvertUTF>

using namespace osgDB;

DynamicLibrary::DynamicLibrary(const std::string& name, HANDLE handle)
{
    _name = name;
    _handle = handle;
    OSG_INFO<<"Opened DynamicLibrary "<<_name<<std::endl;
}

DynamicLibrary::~DynamicLibrary()
{
    if (_handle)
    {
        OSG_INFO<<"Closing DynamicLibrary "<<_name<<std::endl;
#if defined(WIN32) && !defined(__CYGWIN__)
        FreeLibrary((HMODULE)_handle);
#elif defined(__APPLE__) && defined(APPLE_PRE_10_3)
        NSUnLinkModule(static_cast<NSModule>(_handle), FALSE);
#elif defined(__hpux)
        // fortunately, shl_t is a pointer
        shl_unload (static_cast<shl_t>(_handle));
#else // other unix
        dlclose(_handle);
#endif
    }
}

DynamicLibrary* DynamicLibrary::loadLibrary(const std::string& libraryName)
{

    HANDLE handle = NULL;

    std::string fullLibraryName = osgDB::findLibraryFile(libraryName);
    if (!fullLibraryName.empty()) handle = getLibraryHandle( fullLibraryName ); // try the lib we have found
    else handle = getLibraryHandle( libraryName ); // haven't found a lib ourselves, see if the OS can find it simply from the library name.

    if (handle) return new DynamicLibrary(libraryName,handle);

    // else no lib found so report errors.
    OSG_INFO << "DynamicLibrary::failed loading \""<<libraryName<<"\""<<std::endl;

    return NULL;
}

DynamicLibrary::HANDLE DynamicLibrary::getLibraryHandle( const std::string& libraryName)
{
    HANDLE handle = NULL;

#if defined(WIN32) && !defined(__CYGWIN__)
#ifdef OSG_USE_UTF8_FILENAME
    handle = LoadLibraryW(  convertUTF8toUTF16(libraryName).c_str() );
#else
    handle = LoadLibrary( libraryName.c_str() );
#endif
#elif defined(__APPLE__) && defined(APPLE_PRE_10_3)
    NSObjectFileImage image;
    // NSModule os_handle = NULL;
    if (NSCreateObjectFileImageFromFile(libraryName.c_str(), &image) == NSObjectFileImageSuccess) {
        // os_handle = NSLinkModule(image, libraryName.c_str(), TRUE);
        handle = NSLinkModule(image, libraryName.c_str(), TRUE);
        NSDestroyObjectFileImage(image);
    }
#elif defined(__hpux)
    // BIND_FIRST is necessary for some reason
    handle = shl_load ( libraryName.c_str(), BIND_DEFERRED|BIND_FIRST|BIND_VERBOSE, 0);
    return handle;
#else // other unix

    // dlopen will not work with files in the current directory unless
    // they are prefaced with './'  (DB - Nov 5, 2003).
    std::string localLibraryName;
    if( libraryName == osgDB::getSimpleFileName( libraryName ) )
        localLibraryName = "./" + libraryName;
    else
        localLibraryName = libraryName;

    handle = dlopen( localLibraryName.c_str(), RTLD_LAZY | RTLD_GLOBAL);
    if( handle == NULL )
    {
        if (fileExists(localLibraryName))
        {
            OSG_WARN << "Warning: dynamic library '" << libraryName << "' exists, but an error occurred while trying to open it:" << std::endl;
            OSG_WARN << dlerror() << std::endl;
        }
        else
        {
            OSG_INFO << "Warning: dynamic library '" << libraryName << "' does not exist (or isn't readable):" << std::endl;
            OSG_INFO << dlerror() << std::endl;
        }
    }
#endif
    return handle;
}

DynamicLibrary::PROC_ADDRESS DynamicLibrary::getProcAddress(const std::string& procName)
{
    if (_handle==NULL) return NULL;
#if defined(WIN32) && !defined(__CYGWIN__)
    return osg::convertPointerType<DynamicLibrary::PROC_ADDRESS, FARPROC>( GetProcAddress( (HMODULE)_handle, procName.c_str() ) );
#elif defined(__APPLE__) && defined(APPLE_PRE_10_3)
    std::string temp("_");
    NSSymbol symbol;
    temp += procName;   // Mac OS X prepends an underscore on function names
    symbol = NSLookupSymbolInModule(static_cast<NSModule>(_handle), temp.c_str());
    return NSAddressOfSymbol(symbol);
#elif defined(__hpux)
    void* result = NULL;
    if (shl_findsym (reinterpret_cast<shl_t*>(&_handle), procName.c_str(), TYPE_PROCEDURE, result) == 0)
    {
        return result;
    }
    else
    {
        OSG_WARN << "DynamicLibrary::failed looking up " << procName << std::endl;
        OSG_WARN << "DynamicLibrary::error " << strerror(errno) << std::endl;
        return NULL;
    }
#else // other unix
    void* sym = dlsym( _handle,  procName.c_str() );
    if (!sym) {
        OSG_WARN << "DynamicLibrary::failed looking up " << procName << std::endl;
        OSG_WARN << "DynamicLibrary::error " << dlerror() << std::endl;
    }
    return sym;
#endif
}

<commit_msg>Debugging: Hint to debug LoadLibrary issues<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

//The dlopen calls were not adding to OS X until 10.3
#ifdef __APPLE__
#include <AvailabilityMacros.h>
#if !defined(MAC_OS_X_VERSION_10_3) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3)
#define APPLE_PRE_10_3
#endif
#endif

#if defined(WIN32) && !defined(__CYGWIN__)
#include <io.h>
#include <windows.h>
#include <winbase.h>
#elif defined(__APPLE__) && defined(APPLE_PRE_10_3)
#include <mach-o/dyld.h>
#else // all other unix
#include <unistd.h>
#ifdef __hpux
// Although HP-UX has dlopen() it is broken! We therefore need to stick
// to shl_load()/shl_unload()/shl_findsym()
#include <dl.h>
#include <errno.h>
#else
#include <dlfcn.h>
#endif
#endif

#include <osg/Notify>
#include <osg/GLExtensions>

#include <osgDB/DynamicLibrary>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/ConvertUTF>

using namespace osgDB;

DynamicLibrary::DynamicLibrary(const std::string& name, HANDLE handle)
{
    _name = name;
    _handle = handle;
    OSG_INFO<<"Opened DynamicLibrary "<<_name<<std::endl;
}

DynamicLibrary::~DynamicLibrary()
{
    if (_handle)
    {
        OSG_INFO<<"Closing DynamicLibrary "<<_name<<std::endl;
#if defined(WIN32) && !defined(__CYGWIN__)
        FreeLibrary((HMODULE)_handle);
#elif defined(__APPLE__) && defined(APPLE_PRE_10_3)
        NSUnLinkModule(static_cast<NSModule>(_handle), FALSE);
#elif defined(__hpux)
        // fortunately, shl_t is a pointer
        shl_unload (static_cast<shl_t>(_handle));
#else // other unix
        dlclose(_handle);
#endif
    }
}

DynamicLibrary* DynamicLibrary::loadLibrary(const std::string& libraryName)
{

    HANDLE handle = NULL;

    OSG_DEBUG << "DynamicLibrary::try to load library \"" << libraryName << "\"" << std::endl;

    std::string fullLibraryName = osgDB::findLibraryFile(libraryName);
    if (!fullLibraryName.empty()) handle = getLibraryHandle( fullLibraryName ); // try the lib we have found
    else handle = getLibraryHandle( libraryName ); // haven't found a lib ourselves, see if the OS can find it simply from the library name.

    if (handle) return new DynamicLibrary(libraryName,handle);

    // else no lib found so report errors.
    OSG_INFO << "DynamicLibrary::failed loading \""<<libraryName<<"\""<<std::endl;

    return NULL;
}

DynamicLibrary::HANDLE DynamicLibrary::getLibraryHandle( const std::string& libraryName)
{
    HANDLE handle = NULL;

#if defined(WIN32) && !defined(__CYGWIN__)
#ifdef OSG_USE_UTF8_FILENAME
    handle = LoadLibraryW(  convertUTF8toUTF16(libraryName).c_str() );
#else
    handle = LoadLibrary( libraryName.c_str() );
#endif
#elif defined(__APPLE__) && defined(APPLE_PRE_10_3)
    NSObjectFileImage image;
    // NSModule os_handle = NULL;
    if (NSCreateObjectFileImageFromFile(libraryName.c_str(), &image) == NSObjectFileImageSuccess) {
        // os_handle = NSLinkModule(image, libraryName.c_str(), TRUE);
        handle = NSLinkModule(image, libraryName.c_str(), TRUE);
        NSDestroyObjectFileImage(image);
    }
#elif defined(__hpux)
    // BIND_FIRST is necessary for some reason
    handle = shl_load ( libraryName.c_str(), BIND_DEFERRED|BIND_FIRST|BIND_VERBOSE, 0);
    return handle;
#else // other unix

    // dlopen will not work with files in the current directory unless
    // they are prefaced with './'  (DB - Nov 5, 2003).
    std::string localLibraryName;
    if( libraryName == osgDB::getSimpleFileName( libraryName ) )
        localLibraryName = "./" + libraryName;
    else
        localLibraryName = libraryName;

    handle = dlopen( localLibraryName.c_str(), RTLD_LAZY | RTLD_GLOBAL);
    if( handle == NULL )
    {
        if (fileExists(localLibraryName))
        {
            OSG_WARN << "Warning: dynamic library '" << libraryName << "' exists, but an error occurred while trying to open it:" << std::endl;
            OSG_WARN << dlerror() << std::endl;
        }
        else
        {
            OSG_INFO << "Warning: dynamic library '" << libraryName << "' does not exist (or isn't readable):" << std::endl;
            OSG_INFO << dlerror() << std::endl;
        }
    }
#endif
    return handle;
}

DynamicLibrary::PROC_ADDRESS DynamicLibrary::getProcAddress(const std::string& procName)
{
    if (_handle==NULL) return NULL;
#if defined(WIN32) && !defined(__CYGWIN__)
    return osg::convertPointerType<DynamicLibrary::PROC_ADDRESS, FARPROC>( GetProcAddress( (HMODULE)_handle, procName.c_str() ) );
#elif defined(__APPLE__) && defined(APPLE_PRE_10_3)
    std::string temp("_");
    NSSymbol symbol;
    temp += procName;   // Mac OS X prepends an underscore on function names
    symbol = NSLookupSymbolInModule(static_cast<NSModule>(_handle), temp.c_str());
    return NSAddressOfSymbol(symbol);
#elif defined(__hpux)
    void* result = NULL;
    if (shl_findsym (reinterpret_cast<shl_t*>(&_handle), procName.c_str(), TYPE_PROCEDURE, result) == 0)
    {
        return result;
    }
    else
    {
        OSG_WARN << "DynamicLibrary::failed looking up " << procName << std::endl;
        OSG_WARN << "DynamicLibrary::error " << strerror(errno) << std::endl;
        return NULL;
    }
#else // other unix
    void* sym = dlsym( _handle,  procName.c_str() );
    if (!sym) {
        OSG_WARN << "DynamicLibrary::failed looking up " << procName << std::endl;
        OSG_WARN << "DynamicLibrary::error " << dlerror() << std::endl;
    }
    return sym;
#endif
}

<|endoftext|>


<commit_before>//============================================================================
// vSMC/include/vsmc/internal/config.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013-2015, Yan Zhou
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//============================================================================

#ifndef VSMC_INTERNAL_CONFIG_HPP
#define VSMC_INTERNAL_CONFIG_HPP

#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif

#include <vsmc/internal/compiler.hpp>

#ifndef VSMC_NO_STATIC_ASSERT
#define VSMC_NO_STATIC_ASSERT 0
#endif

#ifndef VSMC_NO_RUNTIME_ASSERT
#ifndef NDEBUG
#define VSMC_NO_RUNTIME_ASSERT 0
#else
#define VSMC_NO_RUNTIME_ASSERT 1
#endif
#endif

#ifndef VSMC_NO_RUNTIME_WARNING
#ifndef NDEBUG
#define VSMC_NO_RUNTIME_WARNING 0
#else
#define VSMC_NO_RUNTIME_WARNING 1
#endif
#endif

/// \brief Turn vSMC runtime assertions into exceptions
/// \ingroup Config
#ifndef VSMC_RUNTIME_ASSERT_AS_EXCEPTION
#define VSMC_RUNTIME_ASSERT_AS_EXCEPTION 0
#endif

/// \brief Turn vSMC runtime warnings into exceptions
/// \ingroup Config
#ifndef VSMC_RUNTIME_WARNING_AS_EXCEPTION
#define VSMC_RUNTIME_WARNING_AS_EXCEPTION 0
#endif

// Parallelization features

#ifndef VSMC_HAS_CILK
#define VSMC_HAS_CILK 0
#endif

#ifndef VSMC_HAS_GCD
#define VSMC_HAS_GCD 0
#endif

#ifndef VSMC_HAS_OMP
#define VSMC_HAS_OMP 0
#endif

#ifndef VSMC_HAS_PPL
#define VSMC_HAS_PPL 0
#endif

#ifndef VSMC_HAS_TBB
#define VSMC_HAS_TBB 0
#endif

#ifndef VSMC_HAS_MPI
#define VSMC_HAS_MPI 0
#endif

#ifndef VSMC_HAS_OPENCL
#define VSMC_HAS_OPENCL 0
#endif

// Optional libraries

#ifndef VSMC_HAS_GSL
#define VSMC_HAS_GSL 0
#endif

#ifndef VSMC_HAS_HDF5
#define VSMC_HAS_HDF5 0
#endif

#ifndef VSMC_HAS_JEMALLOC
#define VSMC_HAS_JEMALLOC 0
#endif

#ifndef VSMC_HAS_JEMALLOC_STDAPI
#define VSMC_HAS_JEMALLOC_STDAPI 0
#endif

#ifndef VSMC_HAS_MKL
#define VSMC_HAS_MKL 0
#endif

#ifndef VSMC_USE_MKL_CBLAS
#define VSMC_USE_MKL_CBLAS VSMC_HAS_MKL
#endif

#ifndef VSMC_USE_MKL_VML
#define VSMC_USE_MKL_VML VSMC_HAS_MKL
#endif

#ifndef VSMC_USE_MKL_VSL
#define VSMC_USE_MKL_VSL VSMC_HAS_MKL
#endif

#ifndef VSMC_HAS_ACCELERATE
#define VSMC_HAS_ACCELERATE 0
#endif

#ifndef VSMC_USE_ACCELERATE_CBLAS
#define VSMC_USE_ACCELERATE_CBLAS VSMC_HAS_ACCELERATE
#endif

#ifndef VSMC_USE_ACCELERATE_VFORCE
#define VSMC_USE_ACCELERATE_VFORCE VSMC_HAS_ACCELERATE
#endif

#ifndef VSMC_HAS_TBB_MALLOC
#define VSMC_HAS_TBB_MALLOC VSMC_HAS_TBB
#endif

#endif // VSMC_INTERNAL_CONFIG_HPP
<commit_msg>Add USE_TBB config macro<commit_after>//============================================================================
// vSMC/include/vsmc/internal/config.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013-2015, Yan Zhou
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//============================================================================

#ifndef VSMC_INTERNAL_CONFIG_HPP
#define VSMC_INTERNAL_CONFIG_HPP

#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif

#include <vsmc/internal/compiler.hpp>

#ifndef VSMC_NO_STATIC_ASSERT
#define VSMC_NO_STATIC_ASSERT 0
#endif

#ifndef VSMC_NO_RUNTIME_ASSERT
#ifndef NDEBUG
#define VSMC_NO_RUNTIME_ASSERT 0
#else
#define VSMC_NO_RUNTIME_ASSERT 1
#endif
#endif

#ifndef VSMC_NO_RUNTIME_WARNING
#ifndef NDEBUG
#define VSMC_NO_RUNTIME_WARNING 0
#else
#define VSMC_NO_RUNTIME_WARNING 1
#endif
#endif

/// \brief Turn vSMC runtime assertions into exceptions
/// \ingroup Config
#ifndef VSMC_RUNTIME_ASSERT_AS_EXCEPTION
#define VSMC_RUNTIME_ASSERT_AS_EXCEPTION 0
#endif

/// \brief Turn vSMC runtime warnings into exceptions
/// \ingroup Config
#ifndef VSMC_RUNTIME_WARNING_AS_EXCEPTION
#define VSMC_RUNTIME_WARNING_AS_EXCEPTION 0
#endif

// Parallelization features

#ifndef VSMC_HAS_CILK
#define VSMC_HAS_CILK 0
#endif

#ifndef VSMC_HAS_GCD
#define VSMC_HAS_GCD 0
#endif

#ifndef VSMC_HAS_OMP
#define VSMC_HAS_OMP 0
#endif

#ifndef VSMC_HAS_PPL
#define VSMC_HAS_PPL 0
#endif

#ifndef VSMC_HAS_TBB
#define VSMC_HAS_TBB 0
#endif

#ifndef VSMC_USE_TBB
#define VSMC_USE_TBB VSMC_HAS_TBB
#endif

#ifndef VSMC_HAS_MPI
#define VSMC_HAS_MPI 0
#endif

#ifndef VSMC_HAS_OPENCL
#define VSMC_HAS_OPENCL 0
#endif

// Optional libraries

#ifndef VSMC_HAS_GSL
#define VSMC_HAS_GSL 0
#endif

#ifndef VSMC_HAS_HDF5
#define VSMC_HAS_HDF5 0
#endif

#ifndef VSMC_HAS_JEMALLOC
#define VSMC_HAS_JEMALLOC 0
#endif

#ifndef VSMC_HAS_JEMALLOC_STDAPI
#define VSMC_HAS_JEMALLOC_STDAPI 0
#endif

#ifndef VSMC_HAS_MKL
#define VSMC_HAS_MKL 0
#endif

#ifndef VSMC_USE_MKL_CBLAS
#define VSMC_USE_MKL_CBLAS VSMC_HAS_MKL
#endif

#ifndef VSMC_USE_MKL_VML
#define VSMC_USE_MKL_VML VSMC_HAS_MKL
#endif

#ifndef VSMC_USE_MKL_VSL
#define VSMC_USE_MKL_VSL VSMC_HAS_MKL
#endif

#ifndef VSMC_HAS_ACCELERATE
#define VSMC_HAS_ACCELERATE 0
#endif

#ifndef VSMC_USE_ACCELERATE_CBLAS
#define VSMC_USE_ACCELERATE_CBLAS VSMC_HAS_ACCELERATE
#endif

#ifndef VSMC_USE_ACCELERATE_VFORCE
#define VSMC_USE_ACCELERATE_VFORCE VSMC_HAS_ACCELERATE
#endif

#ifndef VSMC_HAS_TBB_MALLOC
#define VSMC_HAS_TBB_MALLOC VSMC_HAS_TBB
#endif

#endif // VSMC_INTERNAL_CONFIG_HPP
<|endoftext|>


<commit_before>//============================================================================
// include/vsmc/rng/intrin.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distribured under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_INTERNAL_INTRIN_HPP
#define VSMC_INTERNAL_INTRIN_HPP

#include <vsmc/internal/config.hpp>

#ifdef _MSC_VER
#include <intrin.h>
#elif VSMC_HAS_INTRINSIC_FUNCTION
#include <x86intrin.h>
#else
#error x86 intrinsic function is not supported
#endif

#endif // VSMC_INTERNAL_INTRIN_HPP
<commit_msg>remvoe intrin.hpp<commit_after><|endoftext|>