<commit_before>/*  This file is part of the Vc library.

    Copyright (C) 2010 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc 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
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "macros.h"

namespace Vc
{
namespace SSE
{

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerZero::ZEnum)
    : Base(VectorHelper<VectorType>::zero())
{
}

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerOne::OEnum)
    : Base(VectorHelper<T>::one())
{
}

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerIndexesFromZero::IEnum)
    : Base(VectorHelper<VectorType>::load(Base::_IndexesFromZero(), Aligned))
{
}

template<typename T> inline Vector<T> Vector<T>::Zero()
{
    return VectorHelper<VectorType>::zero();
}

template<typename T> inline Vector<T> Vector<T>::IndexesFromZero()
{
    return VectorHelper<VectorType>::load(Base::_IndexesFromZero(), Aligned);
}

template<typename T> template<typename OtherT> inline Vector<T>::Vector(const Vector<OtherT> &x)
    : Base(StaticCastHelper<OtherT, T>::cast(x.data()))
{
}

template<typename T> inline Vector<T>::Vector(EntryType a)
    : Base(VectorHelper<T>::set(a))
{
}

template<typename T> inline Vector<T>::Vector(const EntryType *x)
    : Base(VectorHelper<VectorType>::load(x, Aligned))
{
}

template<typename T> template<typename A> inline Vector<T>::Vector(const EntryType *x, A align)
    : Base(VectorHelper<VectorType>::load(x, align))
{
}

template<typename T> inline Vector<T>::Vector(const Vector<typename CtorTypeHelper<T>::Type> *a)
    : Base(VectorHelper<T>::concat(a[0].data(), a[1].data()))
{
}

template<typename T> inline void Vector<T>::expand(Vector<typename ExpandTypeHelper<T>::Type> *x) const
{
    if (Size == 8u) {
        x[0].data() = VectorHelper<T>::expand0(data());
        x[1].data() = VectorHelper<T>::expand1(data());
    }
}

template<typename T> inline void Vector<T>::load(const EntryType *mem)
{
    data() = VectorHelper<VectorType>::load(mem, Aligned);
}

template<typename T> template<typename A> inline void Vector<T>::load(const EntryType *mem, A align)
{
    data() = VectorHelper<VectorType>::load(mem, align);
}

template<typename T> inline void Vector<T>::makeZero()
{
    data() = VectorHelper<VectorType>::zero();
}

template<typename T> inline void Vector<T>::makeZero(const Mask &k)
{
    data() = VectorHelper<VectorType>::andnot_(mm128_reinterpret_cast<VectorType>(k.data()), data());
}

template<typename T> inline void Vector<T>::store(EntryType *mem) const
{
    VectorHelper<VectorType>::store(mem, data(), Aligned);
}

template<typename T> inline void Vector<T>::store(EntryType *mem, const Mask &mask) const
{
    VectorHelper<VectorType>::store(mem, data(), mm128_reinterpret_cast<VectorType>(mask.data()));
}

template<typename T> template<typename A> inline void Vector<T>::store(EntryType *mem, A align) const
{
    VectorHelper<VectorType>::store(mem, data(), align);
}

template<typename T> template<typename A> inline void Vector<T>::store(EntryType *mem, const Mask &mask, A align) const
{
    store(mem, mask);
}

template<typename T> inline Vector<T> &Vector<T>::operator/=(EntryType x)
{
    if (Base::HasVectorDivision) {
        return operator/=(Vector<T>(x));
    }
    for_all_vector_entries(i,
            d.m(i) /= x;
            );
    return *this;
}

template<typename T> inline Vector<T> Vector<T>::operator/(EntryType x) const
{
    if (Base::HasVectorDivision) {
        return operator/(Vector<T>(x));
    }
    Vector<T> r;
    for_all_vector_entries(i,
            r.d.m(i) = d.m(i) / x;
            );
    return r;
}

template<typename T> inline Vector<T> &Vector<T>::operator/=(const Vector<T> &x)
{
    for_all_vector_entries(i,
            d.m(i) /= x.d.m(i);
            );
    return *this;
}

template<typename T> inline Vector<T> Vector<T>::operator/(const Vector<T> &x) const
{
    Vector<T> r;
    for_all_vector_entries(i,
            r.d.m(i) = d.m(i) / x.d.m(i);
            );
    return r;
}

template<> inline Vector<float> &Vector<float>::operator/=(const Vector<float> &x)
{
    d.v() = _mm_div_ps(d.v(), x.d.v());
    return *this;
}

template<> inline Vector<float> Vector<float>::operator/(const Vector<float> &x) const
{
    return _mm_div_ps(d.v(), x.d.v());
}

template<> inline Vector<float8> &Vector<float8>::operator/=(const Vector<float8> &x)
{
    d.v()[0] = _mm_div_ps(d.v()[0], x.d.v()[0]);
    d.v()[1] = _mm_div_ps(d.v()[1], x.d.v()[1]);
    return *this;
}

template<> inline Vector<float8> Vector<float8>::operator/(const Vector<float8> &x) const
{
    Vector<float8> r;
    r.d.v()[0] = _mm_div_ps(d.v()[0], x.d.v()[0]);
    r.d.v()[1] = _mm_div_ps(d.v()[1], x.d.v()[1]);
    return r;
}

template<> inline Vector<double> &Vector<double>::operator/=(const Vector<double> &x)
{
    d.v() = _mm_div_pd(d.v(), x.d.v());
    return *this;
}

template<> inline Vector<double> Vector<double>::operator/(const Vector<double> &x) const
{
    return _mm_div_pd(d.v(), x.d.v());
}

#define OP_IMPL(T, symbol, fun) \
template<> inline Vector<T> &VectorBase<T>::operator symbol##=(const VectorBase<T> &x) \
{ \
    d.v() = VectorHelper<T>::fun(d.v(), x.d.v()); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T>  VectorBase<T>::operator symbol(const VectorBase<T> &x) const \
{ \
    return Vector<T>(VectorHelper<T>::fun(d.v(), x.d.v())); \
}
OP_IMPL(int, &, and_)
OP_IMPL(int, |, or_)
OP_IMPL(int, ^, xor_)
OP_IMPL(int, <<, sll)
OP_IMPL(int, >>, srl)
OP_IMPL(unsigned int, &, and_)
OP_IMPL(unsigned int, |, or_)
OP_IMPL(unsigned int, ^, xor_)
OP_IMPL(unsigned int, <<, sll)
OP_IMPL(unsigned int, >>, srl)
OP_IMPL(short, &, and_)
OP_IMPL(short, |, or_)
OP_IMPL(short, ^, xor_)
OP_IMPL(short, <<, sll)
OP_IMPL(short, >>, srl)
OP_IMPL(unsigned short, &, and_)
OP_IMPL(unsigned short, |, or_)
OP_IMPL(unsigned short, ^, xor_)
OP_IMPL(unsigned short, <<, sll)
OP_IMPL(unsigned short, >>, srl)
#undef OP_IMPL

#define OP_IMPL(T, SUFFIX) \
template<> inline Vector<T> &VectorBase<T>::operator<<=(int x) \
{ \
    d.v() = CAT(_mm_slli_epi, SUFFIX)(d.v(), x); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T> &VectorBase<T>::operator>>=(int x) \
{ \
    d.v() = CAT(_mm_srli_epi, SUFFIX)(d.v(), x); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T> VectorBase<T>::operator<<(int x) const \
{ \
    return CAT(_mm_slli_epi, SUFFIX)(d.v(), x); \
} \
template<> inline Vector<T> VectorBase<T>::operator>>(int x) const \
{ \
    return CAT(_mm_srli_epi, SUFFIX)(d.v(), x); \
}
OP_IMPL(int, 32)
OP_IMPL(unsigned int, 32)
OP_IMPL(short, 16)
OP_IMPL(unsigned short, 16)
#undef OP_IMPL

} // namespace SSE
} // namespace Vc

#include "undomacros.h"
<commit_msg>unused parameter; add comment that store(T*, Mask) is unaligned<commit_after>/*  This file is part of the Vc library.

    Copyright (C) 2010 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc 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
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "macros.h"

namespace Vc
{
namespace SSE
{

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerZero::ZEnum)
    : Base(VectorHelper<VectorType>::zero())
{
}

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerOne::OEnum)
    : Base(VectorHelper<T>::one())
{
}

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerIndexesFromZero::IEnum)
    : Base(VectorHelper<VectorType>::load(Base::_IndexesFromZero(), Aligned))
{
}

template<typename T> inline Vector<T> Vector<T>::Zero()
{
    return VectorHelper<VectorType>::zero();
}

template<typename T> inline Vector<T> Vector<T>::IndexesFromZero()
{
    return VectorHelper<VectorType>::load(Base::_IndexesFromZero(), Aligned);
}

template<typename T> template<typename OtherT> inline Vector<T>::Vector(const Vector<OtherT> &x)
    : Base(StaticCastHelper<OtherT, T>::cast(x.data()))
{
}

template<typename T> inline Vector<T>::Vector(EntryType a)
    : Base(VectorHelper<T>::set(a))
{
}

template<typename T> inline Vector<T>::Vector(const EntryType *x)
    : Base(VectorHelper<VectorType>::load(x, Aligned))
{
}

template<typename T> template<typename A> inline Vector<T>::Vector(const EntryType *x, A align)
    : Base(VectorHelper<VectorType>::load(x, align))
{
}

template<typename T> inline Vector<T>::Vector(const Vector<typename CtorTypeHelper<T>::Type> *a)
    : Base(VectorHelper<T>::concat(a[0].data(), a[1].data()))
{
}

template<typename T> inline void Vector<T>::expand(Vector<typename ExpandTypeHelper<T>::Type> *x) const
{
    if (Size == 8u) {
        x[0].data() = VectorHelper<T>::expand0(data());
        x[1].data() = VectorHelper<T>::expand1(data());
    }
}

template<typename T> inline void Vector<T>::load(const EntryType *mem)
{
    data() = VectorHelper<VectorType>::load(mem, Aligned);
}

template<typename T> template<typename A> inline void Vector<T>::load(const EntryType *mem, A align)
{
    data() = VectorHelper<VectorType>::load(mem, align);
}

template<typename T> inline void Vector<T>::makeZero()
{
    data() = VectorHelper<VectorType>::zero();
}

template<typename T> inline void Vector<T>::makeZero(const Mask &k)
{
    data() = VectorHelper<VectorType>::andnot_(mm128_reinterpret_cast<VectorType>(k.data()), data());
}

template<typename T> inline void Vector<T>::store(EntryType *mem) const
{
    VectorHelper<VectorType>::store(mem, data(), Aligned);
}

template<typename T> inline void Vector<T>::store(EntryType *mem, const Mask &mask) const
{
    // this executes an unaligned store because SSE does not implement aligned masked stores
    VectorHelper<VectorType>::store(mem, data(), mm128_reinterpret_cast<VectorType>(mask.data()));
}

template<typename T> template<typename A> inline void Vector<T>::store(EntryType *mem, A align) const
{
    VectorHelper<VectorType>::store(mem, data(), align);
}

template<typename T> template<typename A> inline void Vector<T>::store(EntryType *mem, const Mask &mask, A) const
{
    store(mem, mask);
}

template<typename T> inline Vector<T> &Vector<T>::operator/=(EntryType x)
{
    if (Base::HasVectorDivision) {
        return operator/=(Vector<T>(x));
    }
    for_all_vector_entries(i,
            d.m(i) /= x;
            );
    return *this;
}

template<typename T> inline Vector<T> Vector<T>::operator/(EntryType x) const
{
    if (Base::HasVectorDivision) {
        return operator/(Vector<T>(x));
    }
    Vector<T> r;
    for_all_vector_entries(i,
            r.d.m(i) = d.m(i) / x;
            );
    return r;
}

template<typename T> inline Vector<T> &Vector<T>::operator/=(const Vector<T> &x)
{
    for_all_vector_entries(i,
            d.m(i) /= x.d.m(i);
            );
    return *this;
}

template<typename T> inline Vector<T> Vector<T>::operator/(const Vector<T> &x) const
{
    Vector<T> r;
    for_all_vector_entries(i,
            r.d.m(i) = d.m(i) / x.d.m(i);
            );
    return r;
}

template<> inline Vector<float> &Vector<float>::operator/=(const Vector<float> &x)
{
    d.v() = _mm_div_ps(d.v(), x.d.v());
    return *this;
}

template<> inline Vector<float> Vector<float>::operator/(const Vector<float> &x) const
{
    return _mm_div_ps(d.v(), x.d.v());
}

template<> inline Vector<float8> &Vector<float8>::operator/=(const Vector<float8> &x)
{
    d.v()[0] = _mm_div_ps(d.v()[0], x.d.v()[0]);
    d.v()[1] = _mm_div_ps(d.v()[1], x.d.v()[1]);
    return *this;
}

template<> inline Vector<float8> Vector<float8>::operator/(const Vector<float8> &x) const
{
    Vector<float8> r;
    r.d.v()[0] = _mm_div_ps(d.v()[0], x.d.v()[0]);
    r.d.v()[1] = _mm_div_ps(d.v()[1], x.d.v()[1]);
    return r;
}

template<> inline Vector<double> &Vector<double>::operator/=(const Vector<double> &x)
{
    d.v() = _mm_div_pd(d.v(), x.d.v());
    return *this;
}

template<> inline Vector<double> Vector<double>::operator/(const Vector<double> &x) const
{
    return _mm_div_pd(d.v(), x.d.v());
}

#define OP_IMPL(T, symbol, fun) \
template<> inline Vector<T> &VectorBase<T>::operator symbol##=(const VectorBase<T> &x) \
{ \
    d.v() = VectorHelper<T>::fun(d.v(), x.d.v()); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T>  VectorBase<T>::operator symbol(const VectorBase<T> &x) const \
{ \
    return Vector<T>(VectorHelper<T>::fun(d.v(), x.d.v())); \
}
OP_IMPL(int, &, and_)
OP_IMPL(int, |, or_)
OP_IMPL(int, ^, xor_)
OP_IMPL(int, <<, sll)
OP_IMPL(int, >>, srl)
OP_IMPL(unsigned int, &, and_)
OP_IMPL(unsigned int, |, or_)
OP_IMPL(unsigned int, ^, xor_)
OP_IMPL(unsigned int, <<, sll)
OP_IMPL(unsigned int, >>, srl)
OP_IMPL(short, &, and_)
OP_IMPL(short, |, or_)
OP_IMPL(short, ^, xor_)
OP_IMPL(short, <<, sll)
OP_IMPL(short, >>, srl)
OP_IMPL(unsigned short, &, and_)
OP_IMPL(unsigned short, |, or_)
OP_IMPL(unsigned short, ^, xor_)
OP_IMPL(unsigned short, <<, sll)
OP_IMPL(unsigned short, >>, srl)
#undef OP_IMPL

#define OP_IMPL(T, SUFFIX) \
template<> inline Vector<T> &VectorBase<T>::operator<<=(int x) \
{ \
    d.v() = CAT(_mm_slli_epi, SUFFIX)(d.v(), x); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T> &VectorBase<T>::operator>>=(int x) \
{ \
    d.v() = CAT(_mm_srli_epi, SUFFIX)(d.v(), x); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T> VectorBase<T>::operator<<(int x) const \
{ \
    return CAT(_mm_slli_epi, SUFFIX)(d.v(), x); \
} \
template<> inline Vector<T> VectorBase<T>::operator>>(int x) const \
{ \
    return CAT(_mm_srli_epi, SUFFIX)(d.v(), x); \
}
OP_IMPL(int, 32)
OP_IMPL(unsigned int, 32)
OP_IMPL(short, 16)
OP_IMPL(unsigned short, 16)
#undef OP_IMPL

} // namespace SSE
} // namespace Vc

#include "undomacros.h"
<|endoftext|>


<commit_before>#include <common/buffer.h>

#include <ssh/ssh_algorithm_negotiation.h>
#include <ssh/ssh_mac.h>
#include <ssh/ssh_session.h>

namespace {
	struct ssh_mac_algorithm {
		const char *rfc4250_name_;
		CryptoMAC::Algorithm crypto_algorithm_;
		unsigned size_;
	};

	static const struct ssh_mac_algorithm ssh_mac_algorithms[] = {
		{ "hmac-sha1",		CryptoMAC::SHA1,	0 },
		{ "hmac-sha256",	CryptoMAC::SHA256,	0 },
		{ "hmac-md5",		CryptoMAC::MD5,		0 },
		{ "hmac-ripemd160",	CryptoMAC::RIPEMD160,	0 },
		{ "hmac-sha1-96",	CryptoMAC::SHA1,	12 },
		{ "hmac-md5-96",	CryptoMAC::MD5,		12 },
		{ NULL,			CryptoMAC::MD5,		0 }
	};

	class CryptoSSHMAC : public SSH::MAC {
		LogHandle log_;
		CryptoMAC::Instance *instance_;
	public:
		CryptoSSHMAC(const std::string& xname, CryptoMAC::Instance *instance, unsigned xsize)
		: SSH::MAC(xname, xsize == 0 ? instance->size() : xsize, instance->size()),
		  log_("/ssh/mac/crypto/" + xname),
		  instance_(instance)
		{ }

		~CryptoSSHMAC()
		{ }

		MAC *clone(void) const
		{
			return (new CryptoSSHMAC(name_, instance_->clone(), key_size_));
		}

		bool initialize(const Buffer *key)
		{
			return (instance_->initialize(key));
		}

		bool mac(Buffer *out, const Buffer *in)
		{
			return (instance_->mac(out, in));
		}
	};
}

void
SSH::MAC::add_algorithms(Session *session)
{
	const struct ssh_mac_algorithm *alg;

	for (alg = ssh_mac_algorithms; alg->rfc4250_name_ != NULL; alg++) {
		const CryptoMAC::Method *method = CryptoMAC::Method::method(alg->crypto_algorithm_);
		if (method == NULL) {
			DEBUG("/ssh/mac") << "Could not get method for algorithm: " << alg->crypto_algorithm_;
			continue;
		}
		CryptoMAC::Instance *instance = method->instance(alg->crypto_algorithm_);
		if (instance == NULL) {
			DEBUG("/ssh/mac") << "Could not get instance for algorithm: " << alg->crypto_algorithm_;
			continue;
		}
		session->algorithm_negotiation_->add_algorithm(new CryptoSSHMAC(alg->rfc4250_name_, instance, alg->size_));
	}
}

SSH::MAC *
SSH::MAC::algorithm(CryptoMAC::Algorithm xalgorithm)
{
	const struct ssh_mac_algorithm *alg;

	for (alg = ssh_mac_algorithms; alg->rfc4250_name_ != NULL; alg++) {
		if (xalgorithm != alg->crypto_algorithm_)
			continue;
		const CryptoMAC::Method *method = CryptoMAC::Method::method(xalgorithm);
		if (method == NULL) {
			ERROR("/ssh/mac") << "Could not get method for algorithm: " << xalgorithm;
			return (NULL);
		}
		CryptoMAC::Instance *instance = method->instance(xalgorithm);
		if (instance == NULL) {
			ERROR("/ssh/mac") << "Could not get instance for algorithm: " << xalgorithm;
			return (NULL);
		}
		return (new CryptoSSHMAC(alg->rfc4250_name_, instance, alg->size_));
	}
	ERROR("/ssh/mac") << "No SSH MAC support is available for algorithm: " << xalgorithm;
	return (NULL);
}
<commit_msg>Adjust algorithms.<commit_after>#include <common/buffer.h>

#include <ssh/ssh_algorithm_negotiation.h>
#include <ssh/ssh_mac.h>
#include <ssh/ssh_session.h>

namespace {
	struct ssh_mac_algorithm {
		const char *rfc4250_name_;
		CryptoMAC::Algorithm crypto_algorithm_;
		unsigned size_;
	};

	static const struct ssh_mac_algorithm ssh_mac_algorithms[] = {
		{ "hmac-sha1",		CryptoMAC::SHA1,	0 },
		{ "hmac-sha2-256",	CryptoMAC::SHA256,	0 },
		{ "hmac-sha2-512",	CryptoMAC::SHA512,	0 },
		{ "hmac-ripemd160",	CryptoMAC::RIPEMD160,	0 },
		{ "hmac-md5",		CryptoMAC::MD5,		0 },
		{ "hmac-sha1-96",	CryptoMAC::SHA1,	12 },
		{ "hmac-md5-96",	CryptoMAC::MD5,		12 },
		{ NULL,			CryptoMAC::MD5,		0 }
	};

	class CryptoSSHMAC : public SSH::MAC {
		LogHandle log_;
		CryptoMAC::Instance *instance_;
	public:
		CryptoSSHMAC(const std::string& xname, CryptoMAC::Instance *instance, unsigned xsize)
		: SSH::MAC(xname, xsize == 0 ? instance->size() : xsize, instance->size()),
		  log_("/ssh/mac/crypto/" + xname),
		  instance_(instance)
		{ }

		~CryptoSSHMAC()
		{ }

		MAC *clone(void) const
		{
			return (new CryptoSSHMAC(name_, instance_->clone(), key_size_));
		}

		bool initialize(const Buffer *key)
		{
			return (instance_->initialize(key));
		}

		bool mac(Buffer *out, const Buffer *in)
		{
			return (instance_->mac(out, in));
		}
	};
}

void
SSH::MAC::add_algorithms(Session *session)
{
	const struct ssh_mac_algorithm *alg;

	for (alg = ssh_mac_algorithms; alg->rfc4250_name_ != NULL; alg++) {
		const CryptoMAC::Method *method = CryptoMAC::Method::method(alg->crypto_algorithm_);
		if (method == NULL) {
			DEBUG("/ssh/mac") << "Could not get method for algorithm: " << alg->crypto_algorithm_;
			continue;
		}
		CryptoMAC::Instance *instance = method->instance(alg->crypto_algorithm_);
		if (instance == NULL) {
			DEBUG("/ssh/mac") << "Could not get instance for algorithm: " << alg->crypto_algorithm_;
			continue;
		}
		session->algorithm_negotiation_->add_algorithm(new CryptoSSHMAC(alg->rfc4250_name_, instance, alg->size_));
	}
}

SSH::MAC *
SSH::MAC::algorithm(CryptoMAC::Algorithm xalgorithm)
{
	const struct ssh_mac_algorithm *alg;

	for (alg = ssh_mac_algorithms; alg->rfc4250_name_ != NULL; alg++) {
		if (xalgorithm != alg->crypto_algorithm_)
			continue;
		const CryptoMAC::Method *method = CryptoMAC::Method::method(xalgorithm);
		if (method == NULL) {
			ERROR("/ssh/mac") << "Could not get method for algorithm: " << xalgorithm;
			return (NULL);
		}
		CryptoMAC::Instance *instance = method->instance(xalgorithm);
		if (instance == NULL) {
			ERROR("/ssh/mac") << "Could not get instance for algorithm: " << xalgorithm;
			return (NULL);
		}
		return (new CryptoSSHMAC(alg->rfc4250_name_, instance, alg->size_));
	}
	ERROR("/ssh/mac") << "No SSH MAC support is available for algorithm: " << xalgorithm;
	return (NULL);
}
<|endoftext|>


<commit_before>#include <dlfcn.h>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <cstdlib>

#include <iostream>
#include <fstream>
#include <vector>
#include <array>
#include <string>

#define cursor_forward(x) printf("\033[%dC", static_cast<int>(x))
#define cursor_backward(x) printf("\033[%dD", static_cast<int>(x))

typedef ssize_t (*ReadSignature)(int, void*, size_t);

thread_local std::array<char, 1024> lineBuffer;
thread_local auto lineBufferPos = lineBuffer.begin();

thread_local std::string printBuffer;
thread_local std::string::iterator printBufferPos;

thread_local std::vector<std::string> history;
thread_local std::vector<std::string>::iterator historyPos;

static void readHistory() {

    if (history.size()) return;

    std::string historyFileName(getenv("HOME"));
    historyFileName += "/.bash_history";

    std::ifstream historyFile(historyFileName);
    std::string line;

    while (std::getline(historyFile, line))
        history.push_back(line); // TODO: maybe reverse order?

}

static void newlineHandler() {

    lineBuffer.fill(0);
    lineBufferPos = lineBuffer.begin();

}

static void backspaceHandler() {

    if (lineBufferPos != lineBuffer.begin())
        *(--lineBufferPos) = 0;

}

std::string findCompletion(std::vector<std::string>::iterator start, const std::string &pattern) {

    for (auto it = start - 1; it > history.begin(); it--) {
        if (it->compare(0, pattern.length(), pattern) == 0) {
            historyPos = it;
            return *it;
        }
    }

    historyPos = history.end();
    return pattern;

}

void printCompletion(std::vector<std::string>::iterator startIterator) {

    std::string pattern(lineBuffer.data());
    auto completion = findCompletion(startIterator, pattern);

    cursor_forward(1);
    printf("\e[1;30m%s\e[0m", completion.c_str() + pattern.length());
    cursor_backward(completion.length() - pattern.length() + 1);
    fflush(stdout);

}

void regularCharHandler(char c) {

    *lineBufferPos = c;
    lineBufferPos++;

    printCompletion(history.end());

}

void tabHandler() {

    printCompletion(historyPos);

}

static unsigned char yebash(unsigned char c) {

    static char arrowIndicator = 0;
    // TODO: uncomment later
    //if (!getenv("YEBASH"))
    //    return;

    readHistory();

    switch (c) {

        case 0x06: // ctrl+f
            // FIXME: SEGFAULT
            tabHandler();
            c = 0;
            break;

        case 0x0d: // newline
            newlineHandler();
            break;

        case 0x1b: // first arrow char
            arrowIndicator = 1;
            break;

        case 0x5b: // second ...
            if (arrowIndicator == 1)
                arrowIndicator = 2;
            else regularCharHandler(c);
            break;

        case 0x43: // third ...
            if (arrowIndicator == 2) {
                arrowIndicator = 0;
            } else regularCharHandler(c);
            try {
                printBuffer = historyPos->substr(lineBufferPos - lineBuffer.begin());
                printBufferPos = printBuffer.begin();
            } catch (...) {
                // FIXME:
            }
            break;

        case 0x17: // ctrl+w
            newlineHandler(); // TODO: this has to clear lineBuffer
            break;

        case 0x7f: // backspace
            backspaceHandler();
            break;

        default: // regular char or other special chars
            if (c < 0x20)
                newlineHandler();
            else
                regularCharHandler(c);
            break;

    }

    return c;

}

ssize_t read(int fd, void *buf, size_t count) {

    ssize_t returnValue;
    static thread_local ReadSignature realRead = nullptr;

    if (fd == 0) {
        if (printBuffer.length()) {
            *reinterpret_cast<char *>(buf) = *printBufferPos;
            *lineBufferPos =  *printBufferPos++; // TODO: reapeted code
            lineBufferPos++;
            if (printBufferPos == printBuffer.end()) {
                printBuffer.erase(printBuffer.begin(), printBuffer.end());
            }
            return 1;
        }
    }

    if (!realRead)
        realRead = reinterpret_cast<ReadSignature>(dlsym(RTLD_NEXT, "read"));

    returnValue = realRead(fd, buf, count);

    if (fd == 0 && isatty(fileno(stdin)))
        *reinterpret_cast<unsigned char *>(buf) = yebash(*reinterpret_cast<unsigned char *>(buf));

    return returnValue;

}

<commit_msg>Add dummy cleaning after every history suggestion<commit_after>#include <dlfcn.h>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <cstdlib>

#include <iostream>
#include <fstream>
#include <vector>
#include <array>
#include <string>

#define cursor_forward(x) printf("\033[%dC", static_cast<int>(x))
#define cursor_backward(x) printf("\033[%dD", static_cast<int>(x))

typedef ssize_t (*ReadSignature)(int, void*, size_t);

thread_local std::array<char, 1024> lineBuffer;
thread_local auto lineBufferPos = lineBuffer.begin();

thread_local std::string printBuffer;
thread_local std::string::iterator printBufferPos;

thread_local std::vector<std::string> history;
thread_local std::vector<std::string>::iterator historyPos;

static void readHistory() {

    if (history.size()) return;

    std::string historyFileName(getenv("HOME"));
    historyFileName += "/.bash_history";

    std::ifstream historyFile(historyFileName);
    std::string line;

    while (std::getline(historyFile, line))
        history.push_back(line); // TODO: maybe reverse order?

}

static void newlineHandler() {

    lineBuffer.fill(0);
    lineBufferPos = lineBuffer.begin();

}

static void backspaceHandler() {

    if (lineBufferPos != lineBuffer.begin())
        *(--lineBufferPos) = 0;

}

std::string findCompletion(std::vector<std::string>::iterator start, const std::string &pattern) {

    for (auto it = start - 1; it > history.begin(); it--) {
        if (it->compare(0, pattern.length(), pattern) == 0) {
            historyPos = it;
            return *it;
        }
    }

    historyPos = history.end();
    return pattern;

}

void clearTerminalLine() {
    // TODO: get info about terminal width and current cursor position
    // and fix below loops
    for (int i = 0; i < 30; i++)
        printf(" ");
    for (int i = 0; i < 30; i++)
        cursor_backward(1);
}

void printCompletion(std::vector<std::string>::iterator startIterator) {

    std::string pattern(lineBuffer.data());
    auto completion = findCompletion(startIterator, pattern);

    clearTerminalLine();

    cursor_forward(1);
    printf("\e[1;30m%s\e[0m", completion.c_str() + pattern.length());
    cursor_backward(completion.length() - pattern.length() + 1);
    fflush(stdout);

}

void regularCharHandler(char c) {

    *lineBufferPos = c;
    lineBufferPos++;

    printCompletion(history.end());

}

void tabHandler() {

    printCompletion(historyPos);

}

static unsigned char yebash(unsigned char c) {

    static char arrowIndicator = 0;
    // TODO: uncomment later
    //if (!getenv("YEBASH"))
    //    return;

    readHistory();

    switch (c) {

        case 0x06: // ctrl+f
            // FIXME: SEGFAULT
            tabHandler();
            c = 0;
            break;

        case 0x0d: // newline
            newlineHandler();
            break;

        case 0x1b: // first arrow char
            arrowIndicator = 1;
            break;

        case 0x5b: // second ...
            if (arrowIndicator == 1)
                arrowIndicator = 2;
            else regularCharHandler(c);
            break;

        case 0x43: // third ...
            if (arrowIndicator == 2) {
                arrowIndicator = 0;
            } else regularCharHandler(c);
            try {
                printBuffer = historyPos->substr(lineBufferPos - lineBuffer.begin());
                printBufferPos = printBuffer.begin();
            } catch (...) {
                // FIXME:
            }
            break;

        case 0x17: // ctrl+w
            newlineHandler(); // TODO: this has to clear lineBuffer only
            break;

        case 0x7f: // backspace
            backspaceHandler();
            break;

        default: // regular char or other special chars
            if (c < 0x20)
                newlineHandler();
            else
                regularCharHandler(c);
            break;

    }

    return c;

}

ssize_t read(int fd, void *buf, size_t count) {

    ssize_t returnValue;
    static thread_local ReadSignature realRead = nullptr;

    if (fd == 0) { // TODO: make it look good
        if (printBuffer.length()) {
            // Return printBuffer to bash one char at time
            *reinterpret_cast<char *>(buf) = *printBufferPos;
            *lineBufferPos =  *printBufferPos++; // TODO: reapeted code
            lineBufferPos++;
            if (printBufferPos == printBuffer.end()) {
                printBuffer.erase(printBuffer.begin(), printBuffer.end());
            }
            return 1;
        }
    }

    if (!realRead)
        realRead = reinterpret_cast<ReadSignature>(dlsym(RTLD_NEXT, "read"));

    returnValue = realRead(fd, buf, count);

    if (fd == 0 && isatty(fileno(stdin)))
        *reinterpret_cast<unsigned char *>(buf) = yebash(*reinterpret_cast<unsigned char *>(buf));

    return returnValue;

}

<|endoftext|>


<commit_before>//===- ReaderWrappers.cpp - Parse bytecode from file or buffer  -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements loading and parsing a bytecode file and parsing a
// bytecode module from a given buffer.
//
//===----------------------------------------------------------------------===//

#include "llvm/Bytecode/Reader.h"
#include "ReaderInternals.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "Support/StringExtras.h"
#include "Config/fcntl.h"
#include <sys/stat.h>
#include "Config/unistd.h"
#include "Config/sys/mman.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// BytecodeFileReader - Read from an mmap'able file descriptor.
//

namespace {
  /// FDHandle - Simple handle class to make sure a file descriptor gets closed
  /// when the object is destroyed.
  ///
  class FDHandle {
    int FD;
  public:
    FDHandle(int fd) : FD(fd) {}
    operator int() const { return FD; }
    ~FDHandle() {
      if (FD != -1) close(FD);
    }
  };

  /// BytecodeFileReader - parses a bytecode file from a file
  ///
  class BytecodeFileReader : public BytecodeParser {
  private:
    unsigned char *Buffer;
    int Length;

    BytecodeFileReader(const BytecodeFileReader&); // Do not implement
    void operator=(const BytecodeFileReader &BFR); // Do not implement

  public:
    BytecodeFileReader(const std::string &Filename);
    ~BytecodeFileReader();
  };
}

BytecodeFileReader::BytecodeFileReader(const std::string &Filename) {
  FDHandle FD = open(Filename.c_str(), O_RDONLY);
  if (FD == -1)
    throw std::string("Error opening file!");

  // Stat the file to get its length...
  struct stat StatBuf;
  if (fstat(FD, &StatBuf) == -1 || StatBuf.st_size == 0)
    throw std::string("Error stat'ing file!");

  // mmap in the file all at once...
  Length = StatBuf.st_size;
  Buffer = (unsigned char*)mmap(0, Length, PROT_READ, MAP_PRIVATE, FD, 0);

  if (Buffer == (unsigned char*)MAP_FAILED)
    throw std::string("Error mmapping file!");

  try {
    // Parse the bytecode we mmapped in
    ParseBytecode(Buffer, Length, Filename);
  } catch (...) {
    munmap((char*)Buffer, Length);
    throw;
  }
}

BytecodeFileReader::~BytecodeFileReader() {
  // Unmmap the bytecode...
  munmap((char*)Buffer, Length);
}

//===----------------------------------------------------------------------===//
// BytecodeBufferReader - Read from a memory buffer
//

namespace {
  /// BytecodeBufferReader - parses a bytecode file from a buffer
  ///
  class BytecodeBufferReader : public BytecodeParser {
  private:
    const unsigned char *Buffer;
    bool MustDelete;

    BytecodeBufferReader(const BytecodeBufferReader&); // Do not implement
    void operator=(const BytecodeBufferReader &BFR);   // Do not implement

  public:
    BytecodeBufferReader(const unsigned char *Buf, unsigned Length,
                         const std::string &ModuleID);
    ~BytecodeBufferReader();

  };
}

BytecodeBufferReader::BytecodeBufferReader(const unsigned char *Buf,
                                           unsigned Length,
                                           const std::string &ModuleID)
{
  // If not aligned, allocate a new buffer to hold the bytecode...
  const unsigned char *ParseBegin = 0;
  if ((intptr_t)Buf & 3) {
    Buffer = new unsigned char[Length+4];
    unsigned Offset = 4 - ((intptr_t)Buffer & 3);   // Make sure it's aligned
    ParseBegin = Buffer + Offset;
    memcpy((unsigned char*)ParseBegin, Buf, Length);    // Copy it over
    MustDelete = true;
  } else {
    // If we don't need to copy it over, just use the caller's copy
    ParseBegin = Buffer = Buf;
    MustDelete = false;
  }
  try {
    ParseBytecode(ParseBegin, Length, ModuleID);
  } catch (...) {
    if (MustDelete) delete [] Buffer;
    throw;
  }
}

BytecodeBufferReader::~BytecodeBufferReader() {
  if (MustDelete) delete [] Buffer;
}

//===----------------------------------------------------------------------===//
//  BytecodeStdinReader - Read bytecode from Standard Input
//

namespace {
  /// BytecodeStdinReader - parses a bytecode file from stdin
  ///
  class BytecodeStdinReader : public BytecodeParser {
  private:
    std::vector<unsigned char> FileData;
    unsigned char *FileBuf;

    BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
    void operator=(const BytecodeStdinReader &BFR);  // Do not implement

  public:
    BytecodeStdinReader();
  };
}

BytecodeStdinReader::BytecodeStdinReader() {
  int BlockSize;
  unsigned char Buffer[4096*4];

  // Read in all of the data from stdin, we cannot mmap stdin...
  while ((BlockSize = ::read(0 /*stdin*/, Buffer, 4096*4))) {
    if (BlockSize == -1)
      throw std::string("Error reading from stdin!");

    FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
  }

  if (FileData.empty())
    throw std::string("Standard Input empty!");

  FileBuf = &FileData[0];
  ParseBytecode(FileBuf, FileData.size(), "<stdin>");
}

//===----------------------------------------------------------------------===//
//  Varargs transmogrification code...
//

// CheckVarargs - This is used to automatically translate old-style varargs to
// new style varargs for backwards compatibility.
static ModuleProvider *CheckVarargs(ModuleProvider *MP) {
  Module *M = MP->getModule();

  // Check to see if va_start takes arguments...
  Function *F = M->getNamedFunction("llvm.va_start");
  if (F == 0) return MP;  // No varargs use, just return.

  if (F->getFunctionType()->getNumParams() == 0)
    return MP;  // Modern varargs processing, just return.

  // If we get to this point, we know that we have an old-style module.
  // Materialize the whole thing to perform the rewriting.
  MP->materializeModule();

  // If the user is making use of obsolete varargs intrinsics, adjust them for
  // the user.
  if (Function *F = M->getNamedFunction("llvm.va_start")) {
    assert(F->asize() == 1 && "Obsolete va_start takes 1 argument!");

    const Type *RetTy = F->getFunctionType()->getParamType(0);
    RetTy = cast<PointerType>(RetTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_start", RetTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new CallInst(NF, "", CI);
        new StoreInst(V, CI->getOperand(1), CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }

  if (Function *F = M->getNamedFunction("llvm.va_end")) {
    assert(F->asize() == 1 && "Obsolete va_end takes 1 argument!");
    const Type *ArgTy = F->getFunctionType()->getParamType(0);
    ArgTy = cast<PointerType>(ArgTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_end", Type::VoidTy,
                                                  ArgTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new LoadInst(CI->getOperand(1), "", CI);
        new CallInst(NF, V, "", CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }

  if (Function *F = M->getNamedFunction("llvm.va_copy")) {
    assert(F->asize() == 2 && "Obsolete va_copy takes 2 argument!");
    const Type *ArgTy = F->getFunctionType()->getParamType(0);
    ArgTy = cast<PointerType>(ArgTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_copy", ArgTy,
                                                  ArgTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new CallInst(NF, CI->getOperand(2), "", CI);
        new StoreInst(V, CI->getOperand(1), CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }
  return MP;
}

//===----------------------------------------------------------------------===//
// Wrapper functions
//===----------------------------------------------------------------------===//

/// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a
/// buffer
ModuleProvider*
llvm::getBytecodeBufferModuleProvider(const unsigned char *Buffer,
                                      unsigned Length,
                                      const std::string &ModuleID) {
  return CheckVarargs(new BytecodeBufferReader(Buffer, Length, ModuleID));
}

/// ParseBytecodeBuffer - Parse a given bytecode buffer
///
Module *llvm::ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
                                  const std::string &ModuleID,
                                  std::string *ErrorStr){
  try {
    std::auto_ptr<ModuleProvider>
      AMP(getBytecodeBufferModuleProvider(Buffer, Length, ModuleID));
    return AMP->releaseModule();
  } catch (std::string &err) {
    if (ErrorStr) *ErrorStr = err;
    return 0;
  }
}

/// getBytecodeModuleProvider - lazy function-at-a-time loading from a file
///
ModuleProvider *llvm::getBytecodeModuleProvider(const std::string &Filename) {
  if (Filename != std::string("-"))        // Read from a file...
    return CheckVarargs(new BytecodeFileReader(Filename));
  else                                     // Read from stdin
    return CheckVarargs(new BytecodeStdinReader());
}

/// ParseBytecodeFile - Parse the given bytecode file
///
Module *llvm::ParseBytecodeFile(const std::string &Filename,
                                std::string *ErrorStr) {
  try {
    std::auto_ptr<ModuleProvider> AMP(getBytecodeModuleProvider(Filename));
    return AMP->releaseModule();
  } catch (std::string &err) {
    if (ErrorStr) *ErrorStr = err;
    return 0;
  }
}

<commit_msg>Throw better error messages, by calling strerror(errno) when we get an error inside the bytecode reader.<commit_after>//===- ReaderWrappers.cpp - Parse bytecode from file or buffer  -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements loading and parsing a bytecode file and parsing a
// bytecode module from a given buffer.
//
//===----------------------------------------------------------------------===//

#include "llvm/Bytecode/Reader.h"
#include "ReaderInternals.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "Support/StringExtras.h"
#include "Config/fcntl.h"
#include <sys/stat.h>
#include <cerrno>
#include "Config/unistd.h"
#include "Config/sys/mman.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// BytecodeFileReader - Read from an mmap'able file descriptor.
//

namespace {
  /// FDHandle - Simple handle class to make sure a file descriptor gets closed
  /// when the object is destroyed.
  ///
  class FDHandle {
    int FD;
  public:
    FDHandle(int fd) : FD(fd) {}
    operator int() const { return FD; }
    ~FDHandle() {
      if (FD != -1) close(FD);
    }
  };

  /// BytecodeFileReader - parses a bytecode file from a file
  ///
  class BytecodeFileReader : public BytecodeParser {
  private:
    unsigned char *Buffer;
    int Length;

    BytecodeFileReader(const BytecodeFileReader&); // Do not implement
    void operator=(const BytecodeFileReader &BFR); // Do not implement

  public:
    BytecodeFileReader(const std::string &Filename);
    ~BytecodeFileReader();
  };
}

static std::string ErrnoMessage (int savedErrNum, std::string descr) {
   return ::strerror(savedErrNum) + std::string(", while trying to ") + descr;
}

BytecodeFileReader::BytecodeFileReader(const std::string &Filename) {
  FDHandle FD = open(Filename.c_str(), O_RDONLY);
  if (FD == -1)
    throw ErrnoMessage(errno, "open '" + Filename + "'");

  // Stat the file to get its length...
  struct stat StatBuf;
  if (fstat(FD, &StatBuf) == -1 || StatBuf.st_size == 0)
    throw ErrnoMessage(errno, "stat '" + Filename + "'");

  // mmap in the file all at once...
  Length = StatBuf.st_size;
  Buffer = (unsigned char*)mmap(0, Length, PROT_READ, MAP_PRIVATE, FD, 0);

  if (Buffer == (unsigned char*)MAP_FAILED)
    throw ErrnoMessage(errno, "map '" + Filename + "' into memory");

  try {
    // Parse the bytecode we mmapped in
    ParseBytecode(Buffer, Length, Filename);
  } catch (...) {
    munmap((char*)Buffer, Length);
    throw;
  }
}

BytecodeFileReader::~BytecodeFileReader() {
  // Unmmap the bytecode...
  munmap((char*)Buffer, Length);
}

//===----------------------------------------------------------------------===//
// BytecodeBufferReader - Read from a memory buffer
//

namespace {
  /// BytecodeBufferReader - parses a bytecode file from a buffer
  ///
  class BytecodeBufferReader : public BytecodeParser {
  private:
    const unsigned char *Buffer;
    bool MustDelete;

    BytecodeBufferReader(const BytecodeBufferReader&); // Do not implement
    void operator=(const BytecodeBufferReader &BFR);   // Do not implement

  public:
    BytecodeBufferReader(const unsigned char *Buf, unsigned Length,
                         const std::string &ModuleID);
    ~BytecodeBufferReader();

  };
}

BytecodeBufferReader::BytecodeBufferReader(const unsigned char *Buf,
                                           unsigned Length,
                                           const std::string &ModuleID)
{
  // If not aligned, allocate a new buffer to hold the bytecode...
  const unsigned char *ParseBegin = 0;
  if ((intptr_t)Buf & 3) {
    Buffer = new unsigned char[Length+4];
    unsigned Offset = 4 - ((intptr_t)Buffer & 3);   // Make sure it's aligned
    ParseBegin = Buffer + Offset;
    memcpy((unsigned char*)ParseBegin, Buf, Length);    // Copy it over
    MustDelete = true;
  } else {
    // If we don't need to copy it over, just use the caller's copy
    ParseBegin = Buffer = Buf;
    MustDelete = false;
  }
  try {
    ParseBytecode(ParseBegin, Length, ModuleID);
  } catch (...) {
    if (MustDelete) delete [] Buffer;
    throw;
  }
}

BytecodeBufferReader::~BytecodeBufferReader() {
  if (MustDelete) delete [] Buffer;
}

//===----------------------------------------------------------------------===//
//  BytecodeStdinReader - Read bytecode from Standard Input
//

namespace {
  /// BytecodeStdinReader - parses a bytecode file from stdin
  ///
  class BytecodeStdinReader : public BytecodeParser {
  private:
    std::vector<unsigned char> FileData;
    unsigned char *FileBuf;

    BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
    void operator=(const BytecodeStdinReader &BFR);  // Do not implement

  public:
    BytecodeStdinReader();
  };
}

BytecodeStdinReader::BytecodeStdinReader() {
  int BlockSize;
  unsigned char Buffer[4096*4];

  // Read in all of the data from stdin, we cannot mmap stdin...
  while ((BlockSize = ::read(0 /*stdin*/, Buffer, 4096*4))) {
    if (BlockSize == -1)
      throw ErrnoMessage(errno, "read from standard input");

    FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
  }

  if (FileData.empty())
    throw std::string("Standard Input empty!");

  FileBuf = &FileData[0];
  ParseBytecode(FileBuf, FileData.size(), "<stdin>");
}

//===----------------------------------------------------------------------===//
//  Varargs transmogrification code...
//

// CheckVarargs - This is used to automatically translate old-style varargs to
// new style varargs for backwards compatibility.
static ModuleProvider *CheckVarargs(ModuleProvider *MP) {
  Module *M = MP->getModule();

  // Check to see if va_start takes arguments...
  Function *F = M->getNamedFunction("llvm.va_start");
  if (F == 0) return MP;  // No varargs use, just return.

  if (F->getFunctionType()->getNumParams() == 0)
    return MP;  // Modern varargs processing, just return.

  // If we get to this point, we know that we have an old-style module.
  // Materialize the whole thing to perform the rewriting.
  MP->materializeModule();

  // If the user is making use of obsolete varargs intrinsics, adjust them for
  // the user.
  if (Function *F = M->getNamedFunction("llvm.va_start")) {
    assert(F->asize() == 1 && "Obsolete va_start takes 1 argument!");

    const Type *RetTy = F->getFunctionType()->getParamType(0);
    RetTy = cast<PointerType>(RetTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_start", RetTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new CallInst(NF, "", CI);
        new StoreInst(V, CI->getOperand(1), CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }

  if (Function *F = M->getNamedFunction("llvm.va_end")) {
    assert(F->asize() == 1 && "Obsolete va_end takes 1 argument!");
    const Type *ArgTy = F->getFunctionType()->getParamType(0);
    ArgTy = cast<PointerType>(ArgTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_end", Type::VoidTy,
                                                  ArgTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new LoadInst(CI->getOperand(1), "", CI);
        new CallInst(NF, V, "", CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }

  if (Function *F = M->getNamedFunction("llvm.va_copy")) {
    assert(F->asize() == 2 && "Obsolete va_copy takes 2 argument!");
    const Type *ArgTy = F->getFunctionType()->getParamType(0);
    ArgTy = cast<PointerType>(ArgTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_copy", ArgTy,
                                                  ArgTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new CallInst(NF, CI->getOperand(2), "", CI);
        new StoreInst(V, CI->getOperand(1), CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }
  return MP;
}

//===----------------------------------------------------------------------===//
// Wrapper functions
//===----------------------------------------------------------------------===//

/// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a
/// buffer
ModuleProvider*
llvm::getBytecodeBufferModuleProvider(const unsigned char *Buffer,
                                      unsigned Length,
                                      const std::string &ModuleID) {
  return CheckVarargs(new BytecodeBufferReader(Buffer, Length, ModuleID));
}

/// ParseBytecodeBuffer - Parse a given bytecode buffer
///
Module *llvm::ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
                                  const std::string &ModuleID,
                                  std::string *ErrorStr){
  try {
    std::auto_ptr<ModuleProvider>
      AMP(getBytecodeBufferModuleProvider(Buffer, Length, ModuleID));
    return AMP->releaseModule();
  } catch (std::string &err) {
    if (ErrorStr) *ErrorStr = err;
    return 0;
  }
}

/// getBytecodeModuleProvider - lazy function-at-a-time loading from a file
///
ModuleProvider *llvm::getBytecodeModuleProvider(const std::string &Filename) {
  if (Filename != std::string("-"))        // Read from a file...
    return CheckVarargs(new BytecodeFileReader(Filename));
  else                                     // Read from stdin
    return CheckVarargs(new BytecodeStdinReader());
}

/// ParseBytecodeFile - Parse the given bytecode file
///
Module *llvm::ParseBytecodeFile(const std::string &Filename,
                                std::string *ErrorStr) {
  try {
    std::auto_ptr<ModuleProvider> AMP(getBytecodeModuleProvider(Filename));
    return AMP->releaseModule();
  } catch (std::string &err) {
    if (ErrorStr) *ErrorStr = err;
    return 0;
  }
}

<|endoftext|>


<commit_before>//===- MachineCopyPropagation.cpp - Machine Copy Propagation Pass ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is an extremely simple MachineInstr-level copy propagation pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;

#define DEBUG_TYPE "codegen-cp"

STATISTIC(NumDeletes, "Number of dead copies deleted");

namespace {
  class MachineCopyPropagation : public MachineFunctionPass {
    const TargetRegisterInfo *TRI;
    const TargetInstrInfo *TII;
    MachineRegisterInfo *MRI;

  public:
    static char ID; // Pass identification, replacement for typeid
    MachineCopyPropagation() : MachineFunctionPass(ID) {
     initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry());
    }

    bool runOnMachineFunction(MachineFunction &MF) override;

  private:
    typedef SmallVector<unsigned, 4> DestList;
    typedef DenseMap<unsigned, DestList> SourceMap;

    void SourceNoLongerAvailable(unsigned Reg,
                                 SourceMap &SrcMap,
                                 DenseMap<unsigned, MachineInstr*> &AvailCopyMap);
    bool CopyPropagateBlock(MachineBasicBlock &MBB);
  };
}
char MachineCopyPropagation::ID = 0;
char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;

INITIALIZE_PASS(MachineCopyPropagation, "machine-cp",
                "Machine Copy Propagation Pass", false, false)

void
MachineCopyPropagation::SourceNoLongerAvailable(unsigned Reg,
                              SourceMap &SrcMap,
                              DenseMap<unsigned, MachineInstr*> &AvailCopyMap) {
  for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
    SourceMap::iterator SI = SrcMap.find(*AI);
    if (SI != SrcMap.end()) {
      const DestList& Defs = SI->second;
      for (DestList::const_iterator I = Defs.begin(), E = Defs.end();
           I != E; ++I) {
        unsigned MappedDef = *I;
        // Source of copy is no longer available for propagation.
        AvailCopyMap.erase(MappedDef);
        for (MCSubRegIterator SR(MappedDef, TRI); SR.isValid(); ++SR)
          AvailCopyMap.erase(*SR);
      }
    }
  }
}

static bool NoInterveningSideEffect(const MachineInstr *CopyMI,
                                    const MachineInstr *MI) {
  const MachineBasicBlock *MBB = CopyMI->getParent();
  if (MI->getParent() != MBB)
    return false;
  MachineBasicBlock::const_iterator I = CopyMI;
  MachineBasicBlock::const_iterator E = MBB->end();
  MachineBasicBlock::const_iterator E2 = MI;

  ++I;
  while (I != E && I != E2) {
    if (I->hasUnmodeledSideEffects() || I->isCall() ||
        I->isTerminator())
      return false;
    ++I;
  }
  return true;
}

/// isNopCopy - Return true if the specified copy is really a nop. That is
/// if the source of the copy is the same of the definition of the copy that
/// supplied the source. If the source of the copy is a sub-register than it
/// must check the sub-indices match. e.g.
/// ecx = mov eax
/// al  = mov cl
/// But not
/// ecx = mov eax
/// al  = mov ch
static bool isNopCopy(MachineInstr *CopyMI, unsigned Def, unsigned Src,
                      const TargetRegisterInfo *TRI) {
  unsigned SrcSrc = CopyMI->getOperand(1).getReg();
  if (Def == SrcSrc)
    return true;
  if (TRI->isSubRegister(SrcSrc, Def)) {
    unsigned SrcDef = CopyMI->getOperand(0).getReg();
    unsigned SubIdx = TRI->getSubRegIndex(SrcSrc, Def);
    if (!SubIdx)
      return false;
    return SubIdx == TRI->getSubRegIndex(SrcDef, Src);
  }

  return false;
}

bool MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
  SmallSetVector<MachineInstr*, 8> MaybeDeadCopies;  // Candidates for deletion
  DenseMap<unsigned, MachineInstr*> AvailCopyMap;    // Def -> available copies map
  DenseMap<unsigned, MachineInstr*> CopyMap;         // Def -> copies map
  SourceMap SrcMap; // Src -> Def map

  DEBUG(dbgs() << "MCP: CopyPropagateBlock " << MBB.getName() << "\n");

  bool Changed = false;
  for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ) {
    MachineInstr *MI = &*I;
    ++I;

    if (MI->isCopy()) {
      unsigned Def = MI->getOperand(0).getReg();
      unsigned Src = MI->getOperand(1).getReg();

      if (TargetRegisterInfo::isVirtualRegister(Def) ||
          TargetRegisterInfo::isVirtualRegister(Src))
        report_fatal_error("MachineCopyPropagation should be run after"
                           " register allocation!");

      DenseMap<unsigned, MachineInstr*>::iterator CI = AvailCopyMap.find(Src);
      if (CI != AvailCopyMap.end()) {
        MachineInstr *CopyMI = CI->second;
        if (!MRI->isReserved(Def) &&
            (!MRI->isReserved(Src) || NoInterveningSideEffect(CopyMI, MI)) &&
            isNopCopy(CopyMI, Def, Src, TRI)) {
          // The two copies cancel out and the source of the first copy
          // hasn't been overridden, eliminate the second one. e.g.
          //  %ECX<def> = COPY %EAX<kill>
          //  ... nothing clobbered EAX.
          //  %EAX<def> = COPY %ECX
          // =>
          //  %ECX<def> = COPY %EAX
          //
          // Also avoid eliminating a copy from reserved registers unless the
          // definition is proven not clobbered. e.g.
          // %RSP<def> = COPY %RAX
          // CALL
          // %RAX<def> = COPY %RSP

          DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; MI->dump());

          // Clear any kills of Def between CopyMI and MI. This extends the
          // live range.
          for (MachineBasicBlock::iterator I = CopyMI, E = MI; I != E; ++I)
            I->clearRegisterKills(Def, TRI);

          MI->eraseFromParent();
          Changed = true;
          ++NumDeletes;
          continue;
        }
      }

      // If Src is defined by a previous copy, it cannot be eliminated.
      for (MCRegAliasIterator AI(Src, TRI, true); AI.isValid(); ++AI) {
        CI = CopyMap.find(*AI);
        if (CI != CopyMap.end()) {
          DEBUG(dbgs() << "MCP: Copy is no longer dead: "; CI->second->dump());
          MaybeDeadCopies.remove(CI->second);
        }
      }

      DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI->dump());

      // Copy is now a candidate for deletion.
      MaybeDeadCopies.insert(MI);

      // If 'Src' is previously source of another copy, then this earlier copy's
      // source is no longer available. e.g.
      // %xmm9<def> = copy %xmm2
      // ...
      // %xmm2<def> = copy %xmm0
      // ...
      // %xmm2<def> = copy %xmm9
      SourceNoLongerAvailable(Def, SrcMap, AvailCopyMap);

      // Remember Def is defined by the copy.
      // ... Make sure to clear the def maps of aliases first.
      for (MCRegAliasIterator AI(Def, TRI, false); AI.isValid(); ++AI) {
        CopyMap.erase(*AI);
        AvailCopyMap.erase(*AI);
      }
      for (MCSubRegIterator SR(Def, TRI, /*IncludeSelf=*/true); SR.isValid();
           ++SR) {
        CopyMap[*SR] = MI;
        AvailCopyMap[*SR] = MI;
      }

      // Remember source that's copied to Def. Once it's clobbered, then
      // it's no longer available for copy propagation.
      if (std::find(SrcMap[Src].begin(), SrcMap[Src].end(), Def) ==
          SrcMap[Src].end()) {
        SrcMap[Src].push_back(Def);
      }

      continue;
    }

    // Not a copy.
    SmallVector<unsigned, 2> Defs;
    int RegMaskOpNum = -1;
    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      MachineOperand &MO = MI->getOperand(i);
      if (MO.isRegMask())
        RegMaskOpNum = i;
      if (!MO.isReg())
        continue;
      unsigned Reg = MO.getReg();
      if (!Reg)
        continue;

      if (TargetRegisterInfo::isVirtualRegister(Reg))
        report_fatal_error("MachineCopyPropagation should be run after"
                           " register allocation!");

      if (MO.isDef()) {
        Defs.push_back(Reg);
        continue;
      }

      // If 'Reg' is defined by a copy, the copy is no longer a candidate
      // for elimination.
      for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
        DenseMap<unsigned, MachineInstr*>::iterator CI = CopyMap.find(*AI);
        if (CI != CopyMap.end()) {
          DEBUG(dbgs() << "MCP: Copy is used - not dead: "; CI->second->dump());
          MaybeDeadCopies.remove(CI->second);
        }
      }
      // Treat undef use like defs for copy propagation but not for
      // dead copy. We would need to do a liveness check to be sure the copy
      // is dead for undef uses.
      // The backends are allowed to do whatever they want with undef value
      // and we cannot be sure this register will not be rewritten to break
      // some false dependencies for the hardware for instance.
      if (MO.isUndef())
        Defs.push_back(Reg);
    }

    // The instruction has a register mask operand which means that it clobbers
    // a large set of registers.  It is possible to use the register mask to
    // prune the available copies, but treat it like a basic block boundary for
    // now.
    if (RegMaskOpNum >= 0) {
      // Erase any MaybeDeadCopies whose destination register is clobbered.
      const MachineOperand &MaskMO = MI->getOperand(RegMaskOpNum);
      for (SmallSetVector<MachineInstr*, 8>::iterator
           DI = MaybeDeadCopies.begin(), DE = MaybeDeadCopies.end();
           DI != DE; ++DI) {
        unsigned Reg = (*DI)->getOperand(0).getReg();
        if (MRI->isReserved(Reg) || !MaskMO.clobbersPhysReg(Reg))
          continue;
        DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: ";
              (*DI)->dump());
        (*DI)->eraseFromParent();
        Changed = true;
        ++NumDeletes;
      }

      // Clear all data structures as if we were beginning a new basic block.
      MaybeDeadCopies.clear();
      AvailCopyMap.clear();
      CopyMap.clear();
      SrcMap.clear();
      continue;
    }

    for (unsigned i = 0, e = Defs.size(); i != e; ++i) {
      unsigned Reg = Defs[i];

      // No longer defined by a copy.
      for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
        CopyMap.erase(*AI);
        AvailCopyMap.erase(*AI);
      }

      // If 'Reg' is previously source of a copy, it is no longer available for
      // copy propagation.
      SourceNoLongerAvailable(Reg, SrcMap, AvailCopyMap);
    }
  }

  // If MBB doesn't have successors, delete the copies whose defs are not used.
  // If MBB does have successors, then conservative assume the defs are live-out
  // since we don't want to trust live-in lists.
  if (MBB.succ_empty()) {
    for (SmallSetVector<MachineInstr*, 8>::iterator
           DI = MaybeDeadCopies.begin(), DE = MaybeDeadCopies.end();
         DI != DE; ++DI) {
      if (!MRI->isReserved((*DI)->getOperand(0).getReg())) {
        (*DI)->eraseFromParent();
        Changed = true;
        ++NumDeletes;
      }
    }
  }

  return Changed;
}

bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
  if (skipOptnoneFunction(*MF.getFunction()))
    return false;

  bool Changed = false;

  TRI = MF.getSubtarget().getRegisterInfo();
  TII = MF.getSubtarget().getInstrInfo();
  MRI = &MF.getRegInfo();

  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
    Changed |= CopyPropagateBlock(*I);

  return Changed;
}
<commit_msg>[MachineCopyPropagation] Fix comment. NFC<commit_after>//===- MachineCopyPropagation.cpp - Machine Copy Propagation Pass ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is an extremely simple MachineInstr-level copy propagation pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;

#define DEBUG_TYPE "codegen-cp"

STATISTIC(NumDeletes, "Number of dead copies deleted");

namespace {
  class MachineCopyPropagation : public MachineFunctionPass {
    const TargetRegisterInfo *TRI;
    const TargetInstrInfo *TII;
    MachineRegisterInfo *MRI;

  public:
    static char ID; // Pass identification, replacement for typeid
    MachineCopyPropagation() : MachineFunctionPass(ID) {
     initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry());
    }

    bool runOnMachineFunction(MachineFunction &MF) override;

  private:
    typedef SmallVector<unsigned, 4> DestList;
    typedef DenseMap<unsigned, DestList> SourceMap;

    void SourceNoLongerAvailable(unsigned Reg,
                                 SourceMap &SrcMap,
                                 DenseMap<unsigned, MachineInstr*> &AvailCopyMap);
    bool CopyPropagateBlock(MachineBasicBlock &MBB);
  };
}
char MachineCopyPropagation::ID = 0;
char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;

INITIALIZE_PASS(MachineCopyPropagation, "machine-cp",
                "Machine Copy Propagation Pass", false, false)

void
MachineCopyPropagation::SourceNoLongerAvailable(unsigned Reg,
                              SourceMap &SrcMap,
                              DenseMap<unsigned, MachineInstr*> &AvailCopyMap) {
  for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
    SourceMap::iterator SI = SrcMap.find(*AI);
    if (SI != SrcMap.end()) {
      const DestList& Defs = SI->second;
      for (DestList::const_iterator I = Defs.begin(), E = Defs.end();
           I != E; ++I) {
        unsigned MappedDef = *I;
        // Source of copy is no longer available for propagation.
        AvailCopyMap.erase(MappedDef);
        for (MCSubRegIterator SR(MappedDef, TRI); SR.isValid(); ++SR)
          AvailCopyMap.erase(*SR);
      }
    }
  }
}

static bool NoInterveningSideEffect(const MachineInstr *CopyMI,
                                    const MachineInstr *MI) {
  const MachineBasicBlock *MBB = CopyMI->getParent();
  if (MI->getParent() != MBB)
    return false;
  MachineBasicBlock::const_iterator I = CopyMI;
  MachineBasicBlock::const_iterator E = MBB->end();
  MachineBasicBlock::const_iterator E2 = MI;

  ++I;
  while (I != E && I != E2) {
    if (I->hasUnmodeledSideEffects() || I->isCall() ||
        I->isTerminator())
      return false;
    ++I;
  }
  return true;
}

/// isNopCopy - Return true if the specified copy is really a nop. That is
/// if the source of the copy is the same of the definition of the copy that
/// supplied the source. If the source of the copy is a sub-register than it
/// must check the sub-indices match. e.g.
/// ecx = mov eax
/// al  = mov cl
/// But not
/// ecx = mov eax
/// al  = mov ch
static bool isNopCopy(MachineInstr *CopyMI, unsigned Def, unsigned Src,
                      const TargetRegisterInfo *TRI) {
  unsigned SrcSrc = CopyMI->getOperand(1).getReg();
  if (Def == SrcSrc)
    return true;
  if (TRI->isSubRegister(SrcSrc, Def)) {
    unsigned SrcDef = CopyMI->getOperand(0).getReg();
    unsigned SubIdx = TRI->getSubRegIndex(SrcSrc, Def);
    if (!SubIdx)
      return false;
    return SubIdx == TRI->getSubRegIndex(SrcDef, Src);
  }

  return false;
}

bool MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
  SmallSetVector<MachineInstr*, 8> MaybeDeadCopies;  // Candidates for deletion
  DenseMap<unsigned, MachineInstr*> AvailCopyMap;    // Def -> available copies map
  DenseMap<unsigned, MachineInstr*> CopyMap;         // Def -> copies map
  SourceMap SrcMap; // Src -> Def map

  DEBUG(dbgs() << "MCP: CopyPropagateBlock " << MBB.getName() << "\n");

  bool Changed = false;
  for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ) {
    MachineInstr *MI = &*I;
    ++I;

    if (MI->isCopy()) {
      unsigned Def = MI->getOperand(0).getReg();
      unsigned Src = MI->getOperand(1).getReg();

      if (TargetRegisterInfo::isVirtualRegister(Def) ||
          TargetRegisterInfo::isVirtualRegister(Src))
        report_fatal_error("MachineCopyPropagation should be run after"
                           " register allocation!");

      DenseMap<unsigned, MachineInstr*>::iterator CI = AvailCopyMap.find(Src);
      if (CI != AvailCopyMap.end()) {
        MachineInstr *CopyMI = CI->second;
        if (!MRI->isReserved(Def) &&
            (!MRI->isReserved(Src) || NoInterveningSideEffect(CopyMI, MI)) &&
            isNopCopy(CopyMI, Def, Src, TRI)) {
          // The two copies cancel out and the source of the first copy
          // hasn't been overridden, eliminate the second one. e.g.
          //  %ECX<def> = COPY %EAX<kill>
          //  ... nothing clobbered EAX.
          //  %EAX<def> = COPY %ECX
          // =>
          //  %ECX<def> = COPY %EAX
          //
          // Also avoid eliminating a copy from reserved registers unless the
          // definition is proven not clobbered. e.g.
          // %RSP<def> = COPY %RAX
          // CALL
          // %RAX<def> = COPY %RSP

          DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; MI->dump());

          // Clear any kills of Def between CopyMI and MI. This extends the
          // live range.
          for (MachineBasicBlock::iterator I = CopyMI, E = MI; I != E; ++I)
            I->clearRegisterKills(Def, TRI);

          MI->eraseFromParent();
          Changed = true;
          ++NumDeletes;
          continue;
        }
      }

      // If Src is defined by a previous copy, the previous copy cannot be
      // eliminated.
      for (MCRegAliasIterator AI(Src, TRI, true); AI.isValid(); ++AI) {
        CI = CopyMap.find(*AI);
        if (CI != CopyMap.end()) {
          DEBUG(dbgs() << "MCP: Copy is no longer dead: "; CI->second->dump());
          MaybeDeadCopies.remove(CI->second);
        }
      }

      DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI->dump());

      // Copy is now a candidate for deletion.
      MaybeDeadCopies.insert(MI);

      // If 'Def' is previously source of another copy, then this earlier copy's
      // source is no longer available. e.g.
      // %xmm9<def> = copy %xmm2
      // ...
      // %xmm2<def> = copy %xmm0
      // ...
      // %xmm2<def> = copy %xmm9
      SourceNoLongerAvailable(Def, SrcMap, AvailCopyMap);

      // Remember Def is defined by the copy.
      // ... Make sure to clear the def maps of aliases first.
      for (MCRegAliasIterator AI(Def, TRI, false); AI.isValid(); ++AI) {
        CopyMap.erase(*AI);
        AvailCopyMap.erase(*AI);
      }
      for (MCSubRegIterator SR(Def, TRI, /*IncludeSelf=*/true); SR.isValid();
           ++SR) {
        CopyMap[*SR] = MI;
        AvailCopyMap[*SR] = MI;
      }

      // Remember source that's copied to Def. Once it's clobbered, then
      // it's no longer available for copy propagation.
      if (std::find(SrcMap[Src].begin(), SrcMap[Src].end(), Def) ==
          SrcMap[Src].end()) {
        SrcMap[Src].push_back(Def);
      }

      continue;
    }

    // Not a copy.
    SmallVector<unsigned, 2> Defs;
    int RegMaskOpNum = -1;
    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      MachineOperand &MO = MI->getOperand(i);
      if (MO.isRegMask())
        RegMaskOpNum = i;
      if (!MO.isReg())
        continue;
      unsigned Reg = MO.getReg();
      if (!Reg)
        continue;

      if (TargetRegisterInfo::isVirtualRegister(Reg))
        report_fatal_error("MachineCopyPropagation should be run after"
                           " register allocation!");

      if (MO.isDef()) {
        Defs.push_back(Reg);
        continue;
      }

      // If 'Reg' is defined by a copy, the copy is no longer a candidate
      // for elimination.
      for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
        DenseMap<unsigned, MachineInstr*>::iterator CI = CopyMap.find(*AI);
        if (CI != CopyMap.end()) {
          DEBUG(dbgs() << "MCP: Copy is used - not dead: "; CI->second->dump());
          MaybeDeadCopies.remove(CI->second);
        }
      }
      // Treat undef use like defs for copy propagation but not for
      // dead copy. We would need to do a liveness check to be sure the copy
      // is dead for undef uses.
      // The backends are allowed to do whatever they want with undef value
      // and we cannot be sure this register will not be rewritten to break
      // some false dependencies for the hardware for instance.
      if (MO.isUndef())
        Defs.push_back(Reg);
    }

    // The instruction has a register mask operand which means that it clobbers
    // a large set of registers.  It is possible to use the register mask to
    // prune the available copies, but treat it like a basic block boundary for
    // now.
    if (RegMaskOpNum >= 0) {
      // Erase any MaybeDeadCopies whose destination register is clobbered.
      const MachineOperand &MaskMO = MI->getOperand(RegMaskOpNum);
      for (SmallSetVector<MachineInstr*, 8>::iterator
           DI = MaybeDeadCopies.begin(), DE = MaybeDeadCopies.end();
           DI != DE; ++DI) {
        unsigned Reg = (*DI)->getOperand(0).getReg();
        if (MRI->isReserved(Reg) || !MaskMO.clobbersPhysReg(Reg))
          continue;
        DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: ";
              (*DI)->dump());
        (*DI)->eraseFromParent();
        Changed = true;
        ++NumDeletes;
      }

      // Clear all data structures as if we were beginning a new basic block.
      MaybeDeadCopies.clear();
      AvailCopyMap.clear();
      CopyMap.clear();
      SrcMap.clear();
      continue;
    }

    for (unsigned i = 0, e = Defs.size(); i != e; ++i) {
      unsigned Reg = Defs[i];

      // No longer defined by a copy.
      for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
        CopyMap.erase(*AI);
        AvailCopyMap.erase(*AI);
      }

      // If 'Reg' is previously source of a copy, it is no longer available for
      // copy propagation.
      SourceNoLongerAvailable(Reg, SrcMap, AvailCopyMap);
    }
  }

  // If MBB doesn't have successors, delete the copies whose defs are not used.
  // If MBB does have successors, then conservative assume the defs are live-out
  // since we don't want to trust live-in lists.
  if (MBB.succ_empty()) {
    for (SmallSetVector<MachineInstr*, 8>::iterator
           DI = MaybeDeadCopies.begin(), DE = MaybeDeadCopies.end();
         DI != DE; ++DI) {
      if (!MRI->isReserved((*DI)->getOperand(0).getReg())) {
        (*DI)->eraseFromParent();
        Changed = true;
        ++NumDeletes;
      }
    }
  }

  return Changed;
}

bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
  if (skipOptnoneFunction(*MF.getFunction()))
    return false;

  bool Changed = false;

  TRI = MF.getSubtarget().getRegisterInfo();
  TII = MF.getSubtarget().getInstrInfo();
  MRI = &MF.getRegInfo();

  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
    Changed |= CopyPropagateBlock(*I);

  return Changed;
}
<|endoftext|>


<commit_before>// (C) 2014 Arek Olek

#include <iostream>

#include <boost/graph/adjacency_list.hpp>

#include "options.hpp"
#include "test_suite.hpp"
#include "timing.hpp"
#include "bfs.hpp"
#include "lost.hpp"

using namespace std;

typedef boost::adjacency_list<
  boost::hash_setS, boost::vecS, boost::undirectedS
  > graph;
//~ boost::adjacency_matrix<boost::undirectedS> typedef graph;

int main(int argc, char** argv) {
  options opt(argc, argv);
  int z = opt.get<int>("-z", 1);
  int N = opt.get<int>("-n", 500);
  float p = opt.get<float>("-p", 1);

  timing timer;
  lost_light improve;

  for(int n = 100; n <= N; n += 100) {
    test_suite<graph> suite(z, n, p);
    for(auto G : suite) {
      auto T = bfs_tree(G);
      timer.start();
      improve(G, T);
      auto sec = timer.stop();
      cout << "{" << n << "," << sec << "}";
      if(n < N) cout << ",";
      cout << endl;
    }
  }

  return 0;
}
<commit_msg>measure mean time<commit_after>// (C) 2014 Arek Olek

#include <iostream>

#include <boost/graph/adjacency_list.hpp>

#include "options.hpp"
#include "test_suite.hpp"
#include "timing.hpp"
#include "bfs.hpp"
#include "lost.hpp"

using namespace std;

typedef boost::adjacency_list<
  boost::hash_setS, boost::vecS, boost::undirectedS
  > graph;
//~ boost::adjacency_matrix<boost::undirectedS> typedef graph;

int main(int argc, char** argv) {
  options opt(argc, argv);
  int z = opt.get<int>("-z", 1);
  int N = opt.get<int>("-n", 500);
  float p = opt.get<float>("-p", 1);

  timing timer;
  lost_light improve;

  for(int n = 100; n <= N; n += 100) {
    test_suite<graph> suite(z, n, p);
    double total = 0;
    for(auto G : suite) {
      auto T = bfs_tree(G);
      timer.start();
      improve(G, T);
      total += timer.stop();
    }
    cout << "{" << n << "," << total/suite.size() << "}";
    if(n < N) cout << ",";
    cout << endl;
  }

  return 0;
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Javier López-Gómez <jalopezg@inf.uc3m.es>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "DefinitionShadower.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Utils/AST.h"

#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/Stmt.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"

#include <algorithm>

using namespace clang;

namespace cling {
  /// \brief Returns whether the given source location is a Cling input line. If
  /// it came from the prompt, the file is a virtual file with overriden contents.
  static bool typedInClingPrompt(FullSourceLoc L) {
    if (L.isInvalid())
      return false;
    const SourceManager &SM = L.getManager();
    const FileID FID = SM.getFileID(L);
    return SM.isFileOverridden(SM.getFileEntryForID(FID))
           && (SM.getFileID(SM.getIncludeLoc(FID)) == SM.getMainFileID());
  }

  /// \brief Returns whether the given {Function,Tag,Var}Decl/TemplateDecl is a definition.
  static bool isDefinition(const Decl *D) {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      return FD->isThisDeclarationADefinition();
    if (auto TD = dyn_cast<TagDecl>(D))
      return TD->isThisDeclarationADefinition();
    if (auto VD = dyn_cast<VarDecl>(D))
      return VD->isThisDeclarationADefinition();
    if (auto TD = dyn_cast<TemplateDecl>(D))
      return isDefinition(TD->getTemplatedDecl());
    return true;
  }

  /// \brief Returns whether the given declaration is a template instantiation
  /// or specialization.
  static bool isInstantiationOrSpecialization(const Decl *D) {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      return FD->isTemplateInstantiation() || FD->isFunctionTemplateSpecialization();
    if (auto CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
      return CTSD->getSpecializationKind() != TSK_Undeclared;
    if (auto VTSD = dyn_cast<VarTemplateSpecializationDecl>(D))
      return VTSD->getSpecializationKind() != TSK_Undeclared;
    return false;
  }

  DefinitionShadower::DefinitionShadower(Sema& S, Interpreter& I)
          : ASTTransformer(&S), m_Context(S.getASTContext()), m_Interp(I),
            m_TU(S.getASTContext().getTranslationUnitDecl()),
            m_ShadowsDeclInStdDiagID(S.getDiagnostics().getCustomDiagID(
                DiagnosticsEngine::Warning,
                "'%0' shadows a declaration with the same name in the 'std' "
                "namespace; consider using '::%0' to reference this declaration"))
  {}

  bool DefinitionShadower::isClingShadowNamespace(const DeclContext *DC) {
    auto NS = dyn_cast<NamespaceDecl>(DC);
    return NS && NS->getName().startswith("__cling_N5");
  }

  void DefinitionShadower::hideDecl(clang::NamedDecl *D) const {
    // FIXME: this hides a decl from SemaLookup (there is no unloading). For
    // (large) L-values, this might be a memory leak. Should this be fixed?
    if (Scope* S = m_Sema->getScopeForContext(m_TU)) {
      S->RemoveDecl(D);
      if (utils::Analyze::isOnScopeChains(D, *m_Sema))
        m_Sema->IdResolver.RemoveDecl(D);
    }
    clang::StoredDeclsList &SDL = (*m_TU->getLookupPtr())[D->getDeclName()];
    if (SDL.getAsDecl() == D) {
      SDL.setOnlyValue(nullptr);
    }
    if (auto Vec = SDL.getAsVector()) {
      // FIXME: investigate why StoredDeclList has duplicated entries coming from PCM.
      Vec->erase(std::remove_if(Vec->begin(), Vec->end(),
                                [D](Decl *Other) { return cast<Decl>(D) == Other; }),
                 Vec->end());
    }

    if (InterpreterCallbacks *IC = m_Interp.getCallbacks())
      IC->DefinitionShadowed(D);
  }

  void DefinitionShadower::invalidatePreviousDefinitions(NamedDecl *D) const {
    // NotForRedeclaration: lookup anything visible; follows using directives
    LookupResult Previous(*m_Sema, D->getDeclName(), D->getLocation(),
                   Sema::LookupOrdinaryName, Sema::NotForRedeclaration);
    Previous.suppressDiagnostics();
    m_Sema->LookupQualifiedName(Previous, m_TU);
    bool shadowsDeclInStd{};

    for (auto Prev : Previous) {
      if (Prev == D)
        continue;
      if (isDefinition(Prev) && !isDefinition(D))
        continue;
      // If the found declaration is a function overload, do not invalidate it.
      // For templated functions, Sema::IsOverload() does the right thing as per
      // C++ [temp.over.link]p4.
      if (isa<FunctionDecl>(Prev) && isa<FunctionDecl>(D)
          && m_Sema->IsOverload(cast<FunctionDecl>(D),
                                cast<FunctionDecl>(Prev), /*IsForUsingDecl=*/false))
        continue;
      if (isa<FunctionTemplateDecl>(Prev) && isa<FunctionTemplateDecl>(D)
          && m_Sema->IsOverload(cast<FunctionTemplateDecl>(D)->getTemplatedDecl(),
                                cast<FunctionTemplateDecl>(Prev)->getTemplatedDecl(),
                                /*IsForUsingDecl=*/false))
        continue;

      shadowsDeclInStd |= Prev->isInStdNamespace();
      hideDecl(Prev);

      // For unscoped enumerations, also invalidate all enumerators.
      if (EnumDecl *ED = dyn_cast<EnumDecl>(Prev)) {
        if (!ED->isTransparentContext())
          continue;
        for (auto &J : ED->decls())
          if (NamedDecl *ND = dyn_cast<NamedDecl>(J))
            hideDecl(ND);
      }
    }

    // Ignore any forward declaration issued after a definition. Fixes "error
    // : reference to 'xxx' is ambiguous" in `class C {}; class C; C foo;`.
    if (!Previous.empty() && !isDefinition(D))
      D->setInvalidDecl();

    // Diagnose shadowing of decls in the `std` namespace (see ROOT-5971).
    // For unnamed macros, the input is ingested in a single `Interpreter::process()`
    // call. Do not emit the warning in that case, as all references are local
    // to the wrapper function and this diagnostic might be misleading.
    if (shadowsDeclInStd
        && ((m_Interp.getInputFlags() & (Interpreter::kInputFromFile
                                         | Interpreter::kIFFLineByLine))
             != Interpreter::kInputFromFile)) {
      m_Sema->Diag(D->getBeginLoc(), m_ShadowsDeclInStdDiagID)
        << D->getQualifiedNameAsString();
    }
  }

  void DefinitionShadower::invalidatePreviousDefinitions(FunctionDecl *D) const {
    const CompilationOptions &CO = getTransaction()->getCompilationOpts();
    if (utils::Analyze::IsWrapper(D)) {
      if (!CO.DeclarationExtraction)
        return;

      // DeclExtractor shall move local declarations to the TU. Invalidate all
      // previous definitions (that may clash) before it runs.
      auto CS = dyn_cast<CompoundStmt>(D->getBody());
      for (auto &I : CS->body()) {
        auto DS = dyn_cast<DeclStmt>(I);
        if (!DS)
          continue;
        for (auto &J : DS->decls())
          if (auto ND = dyn_cast<NamedDecl>(J))
            invalidatePreviousDefinitions(ND);
      }
    } else
      invalidatePreviousDefinitions(cast<NamedDecl>(D));
  }

  void DefinitionShadower::invalidatePreviousDefinitions(Decl *D) const {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      invalidatePreviousDefinitions(FD);
    else if (auto ND = dyn_cast<NamedDecl>(D))
      invalidatePreviousDefinitions(ND);
  }

  ASTTransformer::Result DefinitionShadower::Transform(Decl* D) {
    Transaction *T = getTransaction();
    if (!T->getCompilationOpts().EnableShadowing)
      return Result(D, true);

    // For variable templates, Transform() is invoked with a VarDecl; get the
    // corresponding VarTemplateDecl.
    if (auto VD = dyn_cast<VarDecl>(D))
      if (auto VTD = VD->getDescribedVarTemplate())
        D = VTD;

    // Disable definition shadowing for some specific cases.
    if (D->getLexicalDeclContext() != m_TU || D->isInvalidDecl()
        || isa<UsingDirectiveDecl>(D) || isa<UsingDecl>(D) || isa<NamespaceDecl>(D)
        || isInstantiationOrSpecialization(D)
        || !typedInClingPrompt(FullSourceLoc{D->getLocation(),
                                             m_Context.getSourceManager()}))
      return Result(D, true);

    // Each transaction gets at most a `__cling_N5xxx' namespace. If `T' already
    // has one, reuse it.
    auto NS = T->getDefinitionShadowNS();
    if (!NS) {
      NS = NamespaceDecl::Create(m_Context, m_TU, /*inline=*/true,
                                 SourceLocation(), SourceLocation(),
                                 &m_Context.Idents.get("__cling_N5"
                                       + std::to_string(m_UniqueNameCounter++)),
                                 nullptr);
      //NS->setImplicit();
      m_TU->addDecl(NS);
      T->setDefinitionShadowNS(NS);
    }

    m_TU->removeDecl(D);
    if (isa<CXXRecordDecl>(D->getDeclContext()))
      D->setLexicalDeclContext(NS);
    else
      D->setDeclContext(NS);
    // An instantiated function template inherits the declaration context of the
    // templated decl. This is used for name mangling; fix it to avoid clashing.
    if (auto FTD = dyn_cast<FunctionTemplateDecl>(D))
      FTD->getTemplatedDecl()->setDeclContext(NS);
    NS->addDecl(D);

    // Invalidate previous definitions so that LookupResult::resolveKind() does not
    // mark resolution as ambiguous.
    invalidatePreviousDefinitions(D);
    return Result(D, true);
  }
} // end namespace cling
<commit_msg>Minor readability/aesthetic changes<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Javier López-Gómez <jalopezg@inf.uc3m.es>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "DefinitionShadower.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Utils/AST.h"

#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/Stmt.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"

#include <algorithm>

using namespace clang;

namespace cling {
  /// \brief Returns whether the given source location is a Cling input line. If
  /// it came from the prompt, the file is a virtual file with overriden contents.
  static bool typedInClingPrompt(FullSourceLoc L) {
    if (L.isInvalid())
      return false;
    const SourceManager &SM = L.getManager();
    const FileID FID = SM.getFileID(L);
    return SM.isFileOverridden(SM.getFileEntryForID(FID))
           && (SM.getFileID(SM.getIncludeLoc(FID)) == SM.getMainFileID());
  }

  /// \brief Returns whether the given {Function,Tag,Var}Decl/TemplateDecl is a definition.
  static bool isDefinition(const Decl *D) {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      return FD->isThisDeclarationADefinition();
    if (auto TD = dyn_cast<TagDecl>(D))
      return TD->isThisDeclarationADefinition();
    if (auto VD = dyn_cast<VarDecl>(D))
      return VD->isThisDeclarationADefinition();
    if (auto TD = dyn_cast<TemplateDecl>(D))
      return isDefinition(TD->getTemplatedDecl());
    return true;
  }

  /// \brief Returns whether the given declaration is a template instantiation
  /// or specialization.
  static bool isInstantiationOrSpecialization(const Decl *D) {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      return FD->isTemplateInstantiation() || FD->isFunctionTemplateSpecialization();
    if (auto CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
      return CTSD->getSpecializationKind() != TSK_Undeclared;
    if (auto VTSD = dyn_cast<VarTemplateSpecializationDecl>(D))
      return VTSD->getSpecializationKind() != TSK_Undeclared;
    return false;
  }

  DefinitionShadower::DefinitionShadower(Sema& S, Interpreter& I)
          : ASTTransformer(&S), m_Context(S.getASTContext()), m_Interp(I),
            m_TU(S.getASTContext().getTranslationUnitDecl()),
            m_ShadowsDeclInStdDiagID(S.getDiagnostics().getCustomDiagID(
                DiagnosticsEngine::Warning,
                "'%0' shadows a declaration with the same name in the 'std' "
                "namespace; use '::%0' to reference this declaration"))
  {}

  bool DefinitionShadower::isClingShadowNamespace(const DeclContext *DC) {
    auto NS = dyn_cast<NamespaceDecl>(DC);
    return NS && NS->getName().startswith("__cling_N5");
  }

  void DefinitionShadower::hideDecl(clang::NamedDecl *D) const {
    // FIXME: this hides a decl from SemaLookup (there is no unloading). For
    // (large) L-values, this might be a memory leak. Should this be fixed?
    if (Scope* S = m_Sema->getScopeForContext(m_TU)) {
      S->RemoveDecl(D);
      if (utils::Analyze::isOnScopeChains(D, *m_Sema))
        m_Sema->IdResolver.RemoveDecl(D);
    }
    clang::StoredDeclsList &SDL = (*m_TU->getLookupPtr())[D->getDeclName()];
    if (SDL.getAsDecl() == D) {
      SDL.setOnlyValue(nullptr);
    }
    if (auto Vec = SDL.getAsVector()) {
      // FIXME: investigate why StoredDeclList has duplicated entries coming from PCM.
      Vec->erase(std::remove_if(Vec->begin(), Vec->end(),
                                [D](Decl *Other) { return cast<Decl>(D) == Other; }),
                 Vec->end());
    }

    if (InterpreterCallbacks *IC = m_Interp.getCallbacks())
      IC->DefinitionShadowed(D);
  }

  void DefinitionShadower::invalidatePreviousDefinitions(NamedDecl *D) const {
    // NotForRedeclaration: lookup anything visible; follows using directives
    LookupResult Previous(*m_Sema, D->getDeclName(), D->getLocation(),
                   Sema::LookupOrdinaryName, Sema::NotForRedeclaration);
    Previous.suppressDiagnostics();
    m_Sema->LookupQualifiedName(Previous, m_TU);
    bool shadowsDeclInStd = false;

    for (auto Prev : Previous) {
      if (Prev == D)
        continue;
      if (isDefinition(Prev) && !isDefinition(D))
        continue;
      // If the found declaration is a function overload, do not invalidate it.
      // For templated functions, Sema::IsOverload() does the right thing as per
      // C++ [temp.over.link]p4.
      if (isa<FunctionDecl>(Prev) && isa<FunctionDecl>(D)
          && m_Sema->IsOverload(cast<FunctionDecl>(D),
                                cast<FunctionDecl>(Prev), /*IsForUsingDecl=*/false))
        continue;
      if (isa<FunctionTemplateDecl>(Prev) && isa<FunctionTemplateDecl>(D)
          && m_Sema->IsOverload(cast<FunctionTemplateDecl>(D)->getTemplatedDecl(),
                                cast<FunctionTemplateDecl>(Prev)->getTemplatedDecl(),
                                /*IsForUsingDecl=*/false))
        continue;

      shadowsDeclInStd |= Prev->isInStdNamespace();
      hideDecl(Prev);

      // For unscoped enumerations, also invalidate all enumerators.
      if (EnumDecl *ED = dyn_cast<EnumDecl>(Prev)) {
        if (!ED->isTransparentContext())
          continue;
        for (auto &J : ED->decls())
          if (NamedDecl *ND = dyn_cast<NamedDecl>(J))
            hideDecl(ND);
      }
    }

    // Ignore any forward declaration issued after a definition. Fixes "error
    // : reference to 'xxx' is ambiguous" in `class C {}; class C; C foo;`.
    if (!Previous.empty() && !isDefinition(D))
      D->setInvalidDecl();

    // Diagnose shadowing of decls in the `std` namespace (see ROOT-5971).
    // For unnamed macros, the input is ingested in a single `Interpreter::process()`
    // call. Do not emit the warning in that case, as all references are local
    // to the wrapper function and this diagnostic might be misleading.
    if (shadowsDeclInStd
        && ((m_Interp.getInputFlags() & (Interpreter::kInputFromFile
                                         | Interpreter::kIFFLineByLine))
             != Interpreter::kInputFromFile)) {
      m_Sema->Diag(D->getBeginLoc(), m_ShadowsDeclInStdDiagID)
        << D->getQualifiedNameAsString();
    }
  }

  void DefinitionShadower::invalidatePreviousDefinitions(FunctionDecl *D) const {
    const CompilationOptions &CO = getTransaction()->getCompilationOpts();
    if (utils::Analyze::IsWrapper(D)) {
      if (!CO.DeclarationExtraction)
        return;

      // DeclExtractor shall move local declarations to the TU. Invalidate all
      // previous definitions (that may clash) before it runs.
      auto CS = dyn_cast<CompoundStmt>(D->getBody());
      for (auto &I : CS->body()) {
        auto DS = dyn_cast<DeclStmt>(I);
        if (!DS)
          continue;
        for (auto &J : DS->decls())
          if (auto ND = dyn_cast<NamedDecl>(J))
            invalidatePreviousDefinitions(ND);
      }
    } else
      invalidatePreviousDefinitions(cast<NamedDecl>(D));
  }

  void DefinitionShadower::invalidatePreviousDefinitions(Decl *D) const {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      invalidatePreviousDefinitions(FD);
    else if (auto ND = dyn_cast<NamedDecl>(D))
      invalidatePreviousDefinitions(ND);
  }

  ASTTransformer::Result DefinitionShadower::Transform(Decl* D) {
    Transaction *T = getTransaction();
    if (!T->getCompilationOpts().EnableShadowing)
      return Result(D, true);

    // For variable templates, Transform() is invoked with a VarDecl; get the
    // corresponding VarTemplateDecl.
    if (auto VD = dyn_cast<VarDecl>(D))
      if (auto VTD = VD->getDescribedVarTemplate())
        D = VTD;

    // Disable definition shadowing for some specific cases.
    if (D->getLexicalDeclContext() != m_TU || D->isInvalidDecl()
        || isa<UsingDirectiveDecl>(D) || isa<UsingDecl>(D) || isa<NamespaceDecl>(D)
        || isInstantiationOrSpecialization(D)
        || !typedInClingPrompt(FullSourceLoc{D->getLocation(),
                                             m_Context.getSourceManager()}))
      return Result(D, true);

    // Each transaction gets at most a `__cling_N5xxx' namespace. If `T' already
    // has one, reuse it.
    auto NS = T->getDefinitionShadowNS();
    if (!NS) {
      NS = NamespaceDecl::Create(m_Context, m_TU, /*inline=*/true,
                                 SourceLocation(), SourceLocation(),
                                 &m_Context.Idents.get("__cling_N5"
                                       + std::to_string(m_UniqueNameCounter++)),
                                 nullptr);
      //NS->setImplicit();
      m_TU->addDecl(NS);
      T->setDefinitionShadowNS(NS);
    }

    m_TU->removeDecl(D);
    if (isa<CXXRecordDecl>(D->getDeclContext()))
      D->setLexicalDeclContext(NS);
    else
      D->setDeclContext(NS);
    // An instantiated function template inherits the declaration context of the
    // templated decl. This is used for name mangling; fix it to avoid clashing.
    if (auto FTD = dyn_cast<FunctionTemplateDecl>(D))
      FTD->getTemplatedDecl()->setDeclContext(NS);
    NS->addDecl(D);

    // Invalidate previous definitions so that LookupResult::resolveKind() does not
    // mark resolution as ambiguous.
    invalidatePreviousDefinitions(D);
    return Result(D, true);
  }
} // end namespace cling
<|endoftext|>