<commit_before>//
//  ClientHandler.cpp
//  ProxyServer
//
//  Created by Hanzhou Shi on 12/16/15.
//  Copyright © 2015 USF. All rights reserved.
//

#include "ClientHandler.hpp"
#include "Utils.hpp"

#include <sstream>

#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <assert.h>

ClientHandler::ClientHandler(const std::string &host, unsigned short port)
: host(host), port(port), dataLen(0), dispatched(false)
{
    resetBuffer();
}

ClientHandler::~ClientHandler() {
}

std::string ClientHandler::dump() {
    return host + ":" + std::to_string(port);
}

void ClientHandler::processRequest(int fd) {
    /// don't reset buffer here, since we could
    /// get partial header.
    if (fillReadBuffer(fd) < 0) return;

    /// get header from current buffer.
    size_t usedDataLen = getLines(buffer, dataLen, lines);
    size_t remainDataLen = dataLen - usedDataLen;
    /// update buffer
    if (usedDataLen < MAX_BUFFER_LEN) {
        /// move unused data to beginning.
        memmove(buffer, buffer+usedDataLen, remainDataLen);
    }
    memset(buffer+remainDataLen, 0, MAX_BUFFER_LEN-remainDataLen);
}

int ClientHandler::fillReadBuffer(int fd) {
    char *bufferStart = ((char *)buffer) + dataLen;
    ssize_t ret = read(fd, bufferStart, MAX_BUFFER_LEN - dataLen);
    if (ret >= 0) dataLen += ret;
    return (int)ret;
}

/// launch a thread to communicate with upstream and
/// forward response to the client using fd.
void ClientHandler::requestUpstreamAndForward(int fd) {
    /// process command.
    std::string cmd = lines.front();
    std::vector<std::string> parts = getPartsFromCmd(cmd);
    if (!parts[2].compare("HTTP/1.1")) parts[2] = "HTTP/1.0";
    cmd = parts[0] + " " + parts[1] + " " + parts[2];

    std::string host = getHostFromUrl(parts[1]);
    int upstream = connectToHost(host);
    if (upstream < 0) {
        std::cerr
        << "connect to upstream failed.. "
        << strerror(errno)
        << std::endl;
        return;
    }
    LSS headers = getHeaderList();

    std::string request = writeHeader(headers, cmd);

    process(request, upstream, fd);
    close(upstream);
}

bool ClientHandler::canDispatch() {
    return lines.size() > 0 && lines.back().size() == 0 && !dispatched;
}

void ClientHandler::setDispatched(bool status) {
    dispatched = status;
}

void *ClientHandler::run(void *args) {
    ClientHandlerArgs *runArgs = (ClientHandlerArgs *)args;
    ClientHandler *client = runArgs->clientHandler;
    client->requestUpstreamAndForward(runArgs->fd);
    delete runArgs;
    return NULL;
}

LSS ClientHandler::getHeaderList() {
    /// split lines into pairs, and strip "User-Agent" and
    /// "referer" browser headers.
    LSS headers;
    for (int i = 1; i < lines.size()-1; ++i) {
        PSS p = pairByColon(lines[i]);
        const std::string &name = p.first;
        const std::string &value = p.second;
        if (!name.compare("REFERER") || !name.compare("USER-AGENT") ||
            !value.compare("Keep-Alive"))
            continue;
        headers.push_back(p);
    }
    lines.clear();
    return headers;
}

std::string ClientHandler::writeHeader(const LSS &headers,
                                       const std::string &cmd) {
    std::string header = cmd + "\r\n";
    for (auto p : headers) header += p.first + ": " + p.second + "\r\n";
    header += "\r\n"; /// an extra CRLF for termination
    return header;
}

void ClientHandler::process(const std::string &req, int us, int ds) {
    debug("request: ");
    debug(req);
    debug("request ended.");

    ssize_t ret = flushBuffer(req.c_str(), req.size(), us);
    if (ret < 0) return;

    getResponseAndForward(us, ds);
}

void ClientHandler::getResponseAndForward(int us, int ds) {
    lines.clear();
    resetBuffer();

    /// process response header first.
    size_t usedDataLen;
    while (fillReadBuffer(us) > 0) {
        usedDataLen = getLines(buffer, dataLen, lines);
        dataLen -= usedDataLen;
        leftShiftData(usedDataLen, dataLen);
        if (lines.size() > 0 && lines.back().size() == 0) break;
    }
    forwardResponseHeader(ds);

    /// forward all data.
    size_t total = 0;
    while (fillReadBuffer(us) > 0) {
        total += dataLen;
        if (flushBuffer(buffer, dataLen, ds) <0) break;
        resetBuffer();
    }
}

void ClientHandler::forwardResponseHeader(int fd) {
    std::string cmd = lines.front();
    std::vector<std::string> parts = getPartsFromCmd(cmd);
    if (!parts[0].compare("HTTP/1.1")) parts[0] = "HTTP/1.0";
    cmd = parts[0] + " " + parts[1] + " " + parts[2];

    LSS headers = getHeaderList();
    std::string header = writeHeader(headers, cmd);
    debug("response: ");
    debug(header);
    debug("response ended.");

    flushBuffer(header.c_str(), header.size(), fd);
}

void ClientHandler::resetBuffer() {
    memset(buffer, 0, MAX_BUFFER_LEN);
    dataLen = 0;
}

void ClientHandler::leftShiftData(size_t lo, size_t len) {
    memmove(buffer, buffer + lo, len);
    memset(buffer+len, 0, MAX_BUFFER_LEN-len);
    dataLen = len;
}

int ClientHandler::flushBuffer(const char *buffer, ssize_t len, int fd) {
    debug(">>> flushing to fd: " + std::to_string(fd) + " <<<");
    ssize_t ret;
    ssize_t consumedLen = 0;
    while (consumedLen < len) {
        ret = write(fd, buffer + consumedLen, len - consumedLen);
        if (ret < 0) {
            error("flush buffer error.");
            return -1;
        }
        consumedLen += ret;
    }
    assert(len == consumedLen);
    return 0;
}
<commit_msg>Get rid of useless output.<commit_after>//
//  ClientHandler.cpp
//  ProxyServer
//
//  Created by Hanzhou Shi on 12/16/15.
//  Copyright © 2015 USF. All rights reserved.
//

#include "ClientHandler.hpp"
#include "Utils.hpp"

#include <sstream>

#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <assert.h>

ClientHandler::ClientHandler(const std::string &host, unsigned short port)
: host(host), port(port), dataLen(0), dispatched(false)
{
    resetBuffer();
}

ClientHandler::~ClientHandler() {
}

std::string ClientHandler::dump() {
    return host + ":" + std::to_string(port);
}

void ClientHandler::processRequest(int fd) {
    /// don't reset buffer here, since we could
    /// get partial header.
    if (fillReadBuffer(fd) < 0) return;

    /// get header from current buffer.
    size_t usedDataLen = getLines(buffer, dataLen, lines);
    size_t remainDataLen = dataLen - usedDataLen;
    /// update buffer
    if (usedDataLen < MAX_BUFFER_LEN) {
        /// move unused data to beginning.
        memmove(buffer, buffer+usedDataLen, remainDataLen);
    }
    memset(buffer+remainDataLen, 0, MAX_BUFFER_LEN-remainDataLen);
}

int ClientHandler::fillReadBuffer(int fd) {
    char *bufferStart = ((char *)buffer) + dataLen;
    ssize_t ret = read(fd, bufferStart, MAX_BUFFER_LEN - dataLen);
    if (ret >= 0) dataLen += ret;
    return (int)ret;
}

/// launch a thread to communicate with upstream and
/// forward response to the client using fd.
void ClientHandler::requestUpstreamAndForward(int fd) {
    /// process command.
    std::string cmd = lines.front();
    std::vector<std::string> parts = getPartsFromCmd(cmd);
    if (!parts[2].compare("HTTP/1.1")) parts[2] = "HTTP/1.0";
    cmd = parts[0] + " " + parts[1] + " " + parts[2];

    std::string host = getHostFromUrl(parts[1]);
    int upstream = connectToHost(host);
    if (upstream < 0) {
        std::cerr
        << "connect to upstream failed.. "
        << strerror(errno)
        << std::endl;
        return;
    }
    LSS headers = getHeaderList();

    std::string request = writeHeader(headers, cmd);

    process(request, upstream, fd);
    close(upstream);
}

bool ClientHandler::canDispatch() {
    return lines.size() > 0 && lines.back().size() == 0 && !dispatched;
}

void ClientHandler::setDispatched(bool status) {
    dispatched = status;
}

void *ClientHandler::run(void *args) {
    ClientHandlerArgs *runArgs = (ClientHandlerArgs *)args;
    ClientHandler *client = runArgs->clientHandler;
    client->requestUpstreamAndForward(runArgs->fd);
    delete runArgs;
    return NULL;
}

LSS ClientHandler::getHeaderList() {
    /// split lines into pairs, and strip "User-Agent" and
    /// "referer" browser headers.
    LSS headers;
    for (int i = 1; i < lines.size()-1; ++i) {
        PSS p = pairByColon(lines[i]);
        const std::string &name = p.first;
        const std::string &value = p.second;
        if (!name.compare("REFERER") || !name.compare("USER-AGENT") ||
            !value.compare("Keep-Alive"))
            continue;
        headers.push_back(p);
    }
    lines.clear();
    return headers;
}

std::string ClientHandler::writeHeader(const LSS &headers,
                                       const std::string &cmd) {
    std::string header = cmd + "\r\n";
    for (auto p : headers) header += p.first + ": " + p.second + "\r\n";
    header += "\r\n"; /// an extra CRLF for termination
    return header;
}

void ClientHandler::process(const std::string &req, int us, int ds) {
    debug("request: ");
    debug(req);
    debug("request ended.");

    ssize_t ret = flushBuffer(req.c_str(), req.size(), us);
    if (ret < 0) return;

    getResponseAndForward(us, ds);
}

void ClientHandler::getResponseAndForward(int us, int ds) {
    lines.clear();
    resetBuffer();

    /// process response header first.
    size_t usedDataLen;
    while (fillReadBuffer(us) > 0) {
        usedDataLen = getLines(buffer, dataLen, lines);
        dataLen -= usedDataLen;
        leftShiftData(usedDataLen, dataLen);
        if (lines.size() > 0 && lines.back().size() == 0) break;
    }
    forwardResponseHeader(ds);

    /// forward all data.
    size_t total = 0;
    while (fillReadBuffer(us) > 0) {
        total += dataLen;
        if (flushBuffer(buffer, dataLen, ds) <0) break;
        resetBuffer();
    }
}

void ClientHandler::forwardResponseHeader(int fd) {
    std::string cmd = lines.front();
    std::vector<std::string> parts = getPartsFromCmd(cmd);
    if (!parts[0].compare("HTTP/1.1")) parts[0] = "HTTP/1.0";
    cmd = parts[0] + " " + parts[1] + " " + parts[2];

    LSS headers = getHeaderList();
    std::string header = writeHeader(headers, cmd);
    debug("response: ");
    debug(header);
    debug("response ended.");

    flushBuffer(header.c_str(), header.size(), fd);
}

void ClientHandler::resetBuffer() {
    memset(buffer, 0, MAX_BUFFER_LEN);
    dataLen = 0;
}

void ClientHandler::leftShiftData(size_t lo, size_t len) {
    memmove(buffer, buffer + lo, len);
    memset(buffer+len, 0, MAX_BUFFER_LEN-len);
    dataLen = len;
}

int ClientHandler::flushBuffer(const char *buffer, ssize_t len, int fd) {
    ssize_t ret;
    ssize_t consumedLen = 0;
    while (consumedLen < len) {
        ret = write(fd, buffer + consumedLen, len - consumedLen);
        if (ret < 0) {
            error("flush buffer error.");
            return -1;
        }
        consumedLen += ret;
    }
    assert(len == consumedLen);
    return 0;
}
<|endoftext|>


<commit_before>/*
 * PrimeSieveProcess.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2012 Kim Walisch, <kim.walisch@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#include "PrimeSieveProcess.hpp"
#include <primesieve/ParallelPrimeSieve.hpp>

#include <QtGlobal>
#include <QStringList>
#include <QCoreApplication>
#include <stdexcept>

#if defined(Q_OS_WIN)
  #include <windows.h>
#else
  #include <unistd.h>
#endif

PrimeSieveProcess::PrimeSieveProcess(QObject* parent) :
  QProcess(parent) {
  sharedMemory_.setParent(parent);
  sharedMemory_.setKey(QString::number(this->getProcessId()));
}

PrimeSieveProcess::~PrimeSieveProcess() {
  // disconnect all signals, must be used to avoid zombie processes
  this->disconnect();
  // kill() and terminate() = trouble, close() works fine
  this->close();
  sharedMemory_.detach();
}

/**
 * Get the process ID of the current process. I tried to use
 * QProcess::pid() but got a lot of trouble on Windows and Mac OS X,
 * also it is not portable.
 */
int PrimeSieveProcess::getProcessId() {
#if defined(Q_OS_WIN)
  return static_cast<int>(GetCurrentProcessId());
#else
  return static_cast<int>(getpid());
#endif
}

/**
 * Create a shared memory segement for communication with the
 * ParallelPrimeSieve process.
 */
void PrimeSieveProcess::createSharedMemory() {
  // attach the shared memory
  if (!sharedMemory_.isAttached() &&
      !sharedMemory_.create(sizeof(shm_))) {
    throw std::runtime_error(
        "Interprocess communication error, could not allocate shared memory.");
  }
  // map the attached shared memory to the shm_ segment
  shm_ = static_cast<primesieve::ParallelPrimeSieve::SharedMemory*>(sharedMemory_.data());
}

/**
 * Start a new ParallelPrimeSieve process that sieves
 * the primes within [start, stop].
 */
void PrimeSieveProcess::start(quint64 start, quint64 stop,
    int sieveSize, int flags, int threads) {
  this->createSharedMemory();
  // initialize the shared memory segment
  shm_->start = start;
  shm_->stop = stop;
  shm_->sieveSize = sieveSize;
  shm_->flags = flags;
  shm_->threads = threads;
  shm_->status = 0.0;
  shm_->seconds = 0.0;
  for (int i = 0; i < 6; i++)
    shm_->counts[i] = 0;
  // path + file name of the aplication
  QString path = QCoreApplication::applicationFilePath();
  // process arguments, see main.cpp
  QStringList args;
  args << "PrimeSieveProcess" << sharedMemory_.key();
  /// start a new ParallelPrimeSieve process
  /// @see main.cpp
  QProcess::start(path, args, QIODevice::ReadOnly);
}

bool PrimeSieveProcess::isFinished() {
  return (static_cast<int>(shm_->status) == 100);
}

/**
 * @return The count of primes/k-tuplets within [start, stop].
 * @pre index < 6
 */
quint64 PrimeSieveProcess::getCount(unsigned int index) const {
  return shm_->counts[index];
}

/**
 * @return The sieving status in percent.
 */
double PrimeSieveProcess::getStatus() const {
  return shm_->status;
}

/**
 * @return The time elapsed in seconds (if sieving is finished).
 */
double PrimeSieveProcess::getSeconds() const {
  return shm_->seconds;
}
<commit_msg>Fix comment<commit_after>/*
 * PrimeSieveProcess.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2012 Kim Walisch, <kim.walisch@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#include "PrimeSieveProcess.hpp"
#include <primesieve/ParallelPrimeSieve.hpp>

#include <QtGlobal>
#include <QStringList>
#include <QCoreApplication>
#include <stdexcept>

#if defined(Q_OS_WIN)
  #include <windows.h>
#else
  #include <unistd.h>
#endif

PrimeSieveProcess::PrimeSieveProcess(QObject* parent) :
  QProcess(parent) {
  sharedMemory_.setParent(parent);
  sharedMemory_.setKey(QString::number(this->getProcessId()));
}

PrimeSieveProcess::~PrimeSieveProcess() {
  // disconnect all signals, must be used to avoid zombie processes
  this->disconnect();
  // kill() and terminate() = trouble, close() works fine
  this->close();
  sharedMemory_.detach();
}

/**
 * Get the process ID of the current process. I tried to use
 * QProcess::pid() but got a lot of trouble on Windows and Mac OS X,
 * also it is not portable.
 */
int PrimeSieveProcess::getProcessId() {
#if defined(Q_OS_WIN)
  return static_cast<int>(GetCurrentProcessId());
#else
  return static_cast<int>(getpid());
#endif
}

/**
 * Create a shared memory segment for communication with the
 * ParallelPrimeSieve process.
 */
void PrimeSieveProcess::createSharedMemory() {
  // attach the shared memory
  if (!sharedMemory_.isAttached() &&
      !sharedMemory_.create(sizeof(shm_))) {
    throw std::runtime_error(
        "Interprocess communication error, could not allocate shared memory.");
  }
  // map the attached shared memory to the shm_ segment
  shm_ = static_cast<primesieve::ParallelPrimeSieve::SharedMemory*>(sharedMemory_.data());
}

/**
 * Start a new ParallelPrimeSieve process that sieves
 * the primes within [start, stop].
 */
void PrimeSieveProcess::start(quint64 start, quint64 stop,
    int sieveSize, int flags, int threads) {
  this->createSharedMemory();
  // initialize the shared memory segment
  shm_->start = start;
  shm_->stop = stop;
  shm_->sieveSize = sieveSize;
  shm_->flags = flags;
  shm_->threads = threads;
  shm_->status = 0.0;
  shm_->seconds = 0.0;
  for (int i = 0; i < 6; i++)
    shm_->counts[i] = 0;
  // path + file name of the aplication
  QString path = QCoreApplication::applicationFilePath();
  // process arguments, see main.cpp
  QStringList args;
  args << "PrimeSieveProcess" << sharedMemory_.key();
  /// start a new ParallelPrimeSieve process
  /// @see main.cpp
  QProcess::start(path, args, QIODevice::ReadOnly);
}

bool PrimeSieveProcess::isFinished() {
  return (static_cast<int>(shm_->status) == 100);
}

/**
 * @return The count of primes/k-tuplets within [start, stop].
 * @pre index < 6
 */
quint64 PrimeSieveProcess::getCount(unsigned int index) const {
  return shm_->counts[index];
}

/**
 * @return The sieving status in percent.
 */
double PrimeSieveProcess::getStatus() const {
  return shm_->status;
}

/**
 * @return The time elapsed in seconds (if sieving is finished).
 */
double PrimeSieveProcess::getSeconds() const {
  return shm_->seconds;
}
<|endoftext|>


<commit_before>#include <SDKDDKVer.h>
#include <windows.h>
#include <iostream>
#include <sstream>
#include <chrono>
#include <random>
#include "../src/SQFGenerator.h"
#include "../src/SQFGenerator.cpp"

typedef void (__stdcall *RVExtension_t)(char *output, int outputSize, const char *function);

RVExtension_t RVExtension;

void test()
{
    char output[10*1024];
    const int iterations = 10000;
    const char *command = "['pythia.ping', 'asd', 'ert', 3]";

    std::cout << "Calling " << iterations << " times: " << command << std::endl;

    // First call to initialize everything (in case it is needed)
    RVExtension(output, sizeof(output), command);

    auto start = std::chrono::system_clock::now();
    for (int i = iterations; i > 0; i--)
    {
        RVExtension(output, sizeof(output), command);
    }
    auto end = std::chrono::system_clock::now();
    auto elapsed = end - start;

    std::cout << "Last call output: " << output << std::endl;
    std::cout << "Each function time: " << elapsed.count() / 10000.0 / (double)iterations << "ms" << std::endl;
}

std::string createPingRequest(std::string sqf)
{
    if (sqf == "[]")
    {
        return std::string("['pythia.ping']");
    }
    else
    {
        return std::string("['pythia.ping', ") + (sqf.c_str()+1);
    }
}

void parseMultipart(const char *output, int &id, int &count)
{
    // Poor man's parsing :)
    std::stringstream ss(output);
    std::string start;
    std::string comma;
    std::string count_s;

    ss >> start;
    ss >> id;
    ss >> comma;
    ss >> count_s;
    count = atoi(count_s.c_str());
}

int compareRegularResponse(const char *response, std::string &expected)
{
    const char responseTemplate[] = "[\"r\",";
    const int payloadOffset = sizeof(responseTemplate) - 1;

    if (strncmp(response, responseTemplate, payloadOffset) == 0)
    {
        if (!strncmp(response + payloadOffset, expected.c_str(), expected.size()))
        {
            if (!strcmp(response + payloadOffset + expected.size(), "]"))
            {
                return 0;
            }
        }

        std::cout << "Expected: " << response << expected << "]" << std::endl;
        std::cout << "Got:      " << response << std::endl;
        return 1;
    }

    return -1; // Not a regular response
}

std::string handleMultipart(int id, int count)
{
    char output[10 * 1024];
    std::string multipartRequest = std::string("['pythia.multipart',") + std::to_string(id) + ']';
    std::string fullOutput;

    for (int i = 0; i < count; i++)
    {
        output[0] = '\0';
        RVExtension(output, sizeof(output), multipartRequest.c_str());
        fullOutput += output;
    }
    //std::cout << fullOutput << std::endl;
    return fullOutput;
}

int test_fuzzing_single()
{
    char output[10 * 1024];

    const char multipartTemplate[] = "[\"m\",";
    const int payloadOffset = sizeof(multipartTemplate) - 1;

    SQFGenerator builder = SQFGenerator(0, 100);
    std::string sqf = builder.generate(2);
    std::string request = createPingRequest(sqf);

    RVExtension(output, sizeof(output), request.c_str());

    // Check for regular response
    int regularResponse = compareRegularResponse(output, sqf);
    if (regularResponse != -1)
        return regularResponse;

    if (strncmp(output, multipartTemplate, payloadOffset) == 0)
    {
        //std::cout << output << std::endl;
        int id, count;
        parseMultipart(output, id, count);
        std::string multipartOutput = handleMultipart(id, count);

        int multipartResponse = compareRegularResponse(multipartOutput.c_str(), sqf);
        if (multipartResponse == 0)
        {
            //std::cout << "OK :)" << std::endl;
            return 0;
        }
        else
        {
            std::cout << "Got unknown response: " << multipartOutput << std::endl;
            return 1;
        }
    }
    else
    {
        std::cout << "Got unknown response: " << output << std::endl;
        return 1;
    }
}

void test_fuzzing_multiple()
{
    for (int i = 0; i < 10000; i++)
    {
        if (i % 10 == 0)
            std::cout << "Test: " << std::to_string(i) << std::endl;

        if (test_fuzzing_single() != 0)
            return;
    }
    std::cout << "Tests OK!" << std::endl;
}

void test_coroutines()
{
    char output[10 * 1024];
    const int iterations = 10000;
    const char *command = "['python.coroutines.test_coroutines']";
    char *response = _strdup("['pythia.continue',         , 'tralala something']");
    char number[10];

    int continue_val;

    std::cout << "Calling " << iterations << " times: " << command << std::endl;

    // First call to initialize everything (in case it is needed)
    RVExtension(output, sizeof(output), command);

    auto start = std::chrono::system_clock::now();
    for (int i = iterations; i > 0; i--)
    {
        RVExtension(output, sizeof(output), command);
        while (output[2] == 's')
        {
            continue_val = atoi(output + 5);
            sprintf_s(number, "%6d", continue_val);
            for (int j = 0; j < 6; j++)
            {
                response[20 + j] = number[j];
            }
            RVExtension(output, sizeof(output), response);
        }
    }
    auto end = std::chrono::system_clock::now();
    auto elapsed = end - start;

    std::cout << "Last call output: " << output << std::endl;
    std::cout << "Each function time: " << elapsed.count() / 10000.0 / (double)iterations << "ms" << std::endl;
}

#ifdef _WIN64
#define PYTHIA_DLL "Pythia_x64.dll"
#define FUNCNAME "RVExtension"
#else
#define PYTHIA_DLL "Pythia.dll"
#define FUNCNAME "_RVExtension@12"
#endif

int main()
{
    HINSTANCE hInstLibrary = LoadLibrary(TEXT(PYTHIA_DLL));

    if (hInstLibrary)
    {
        RVExtension = (RVExtension_t)GetProcAddress(hInstLibrary, FUNCNAME);

        if (RVExtension)
        {
            test();
        }
        else
        {
            std::cout << "Could not get RVExtension function." << std::endl;
        }
        FreeLibrary(hInstLibrary);
    }
    else
    {
        std::cout << "Could not open library dll." << std::endl;
    }

    std::cout << "Press enter to continue...";
    std::cin.get();
    return 0;
}

<commit_msg>Count time for fuzzing<commit_after>#include <SDKDDKVer.h>
#include <windows.h>
#include <iostream>
#include <sstream>
#include <chrono>
#include <random>
#include "../src/SQFGenerator.h"
#include "../src/SQFGenerator.cpp"

typedef void (__stdcall *RVExtension_t)(char *output, int outputSize, const char *function);

RVExtension_t RVExtension;

void test()
{
    char output[10*1024];
    const int iterations = 10000;
    const char *command = "['pythia.ping', 'asd', 'ert', 3]";

    std::cout << "Calling " << iterations << " times: " << command << std::endl;

    // First call to initialize everything (in case it is needed)
    RVExtension(output, sizeof(output), command);

    auto start = std::chrono::system_clock::now();
    for (int i = iterations; i > 0; i--)
    {
        RVExtension(output, sizeof(output), command);
    }
    auto end = std::chrono::system_clock::now();
    auto elapsed = end - start;

    std::cout << "Last call output: " << output << std::endl;
    std::cout << "Each function time: " << elapsed.count() / 10000.0 / (double)iterations << "ms" << std::endl;
}

std::string createPingRequest(std::string sqf)
{
    if (sqf == "[]")
    {
        return std::string("['pythia.ping']");
    }
    else
    {
        return std::string("['pythia.ping', ") + (sqf.c_str()+1);
    }
}

void parseMultipart(const char *output, int &id, int &count)
{
    // Poor man's parsing :)
    std::stringstream ss(output);
    std::string start;
    std::string comma;
    std::string count_s;

    ss >> start;
    ss >> id;
    ss >> comma;
    ss >> count_s;
    count = atoi(count_s.c_str());
}

int compareRegularResponse(const char *response, std::string &expected)
{
    const char responseTemplate[] = "[\"r\",";
    const int payloadOffset = sizeof(responseTemplate) - 1;

    if (strncmp(response, responseTemplate, payloadOffset) == 0)
    {
        if (!strncmp(response + payloadOffset, expected.c_str(), expected.size()))
        {
            if (!strcmp(response + payloadOffset + expected.size(), "]"))
            {
                return 0;
            }
        }

        std::cout << "Expected: " << response << expected << "]" << std::endl;
        std::cout << "Got:      " << response << std::endl;
        return 1;
    }

    return -1; // Not a regular response
}

std::string handleMultipart(int id, int count)
{
    char output[10 * 1024];
    std::string multipartRequest = std::string("['pythia.multipart',") + std::to_string(id) + ']';
    std::string fullOutput;

    for (int i = 0; i < count; i++)
    {
        output[0] = '\0';
        RVExtension(output, sizeof(output), multipartRequest.c_str());
        fullOutput += output;
    }
    //std::cout << fullOutput << std::endl;
    return fullOutput;
}

int test_fuzzing_single()
{
    char output[10 * 1024];

    const char multipartTemplate[] = "[\"m\",";
    const int payloadOffset = sizeof(multipartTemplate) - 1;

    SQFGenerator builder = SQFGenerator(0, 100);
    std::string sqf = builder.generate(2);
    std::string request = createPingRequest(sqf);

    RVExtension(output, sizeof(output), request.c_str());

    // Check for regular response
    int regularResponse = compareRegularResponse(output, sqf);
    if (regularResponse != -1)
        return regularResponse;

    if (strncmp(output, multipartTemplate, payloadOffset) == 0)
    {
        //std::cout << output << std::endl;
        int id, count;
        parseMultipart(output, id, count);
        std::string multipartOutput = handleMultipart(id, count);

        int multipartResponse = compareRegularResponse(multipartOutput.c_str(), sqf);
        if (multipartResponse == 0)
        {
            //std::cout << "OK :)" << std::endl;
            return 0;
        }
        else
        {
            std::cout << "Got unknown response: " << multipartOutput << std::endl;
            return 1;
        }
    }
    else
    {
        std::cout << "Got unknown response: " << output << std::endl;
        return 1;
    }
}

void test_fuzzing_multiple()
{
    int iterations = 10000;

    auto start = std::chrono::system_clock::now();
    for (int i = 0; i < iterations; i++)
    {
        if (i % 10 == 0)
            std::cout << "Test: " << std::to_string(i) << std::endl;

        if (test_fuzzing_single() != 0)
            return;
    }
    auto end = std::chrono::system_clock::now();
    auto elapsed = end - start;
    std::cout << "Tests OK!" << std::endl;
    std::cout << "Each function time: " << elapsed.count() / 10000.0 / (double)iterations << "ms" << std::endl;
}

void test_coroutines()
{
    char output[10 * 1024];
    const int iterations = 10000;
    const char *command = "['python.coroutines.test_coroutines']";
    char *response = _strdup("['pythia.continue',         , 'tralala something']");
    char number[10];

    int continue_val;

    std::cout << "Calling " << iterations << " times: " << command << std::endl;

    // First call to initialize everything (in case it is needed)
    RVExtension(output, sizeof(output), command);

    auto start = std::chrono::system_clock::now();
    for (int i = iterations; i > 0; i--)
    {
        RVExtension(output, sizeof(output), command);
        while (output[2] == 's')
        {
            continue_val = atoi(output + 5);
            sprintf_s(number, "%6d", continue_val);
            for (int j = 0; j < 6; j++)
            {
                response[20 + j] = number[j];
            }
            RVExtension(output, sizeof(output), response);
        }
    }
    auto end = std::chrono::system_clock::now();
    auto elapsed = end - start;

    std::cout << "Last call output: " << output << std::endl;
    std::cout << "Each function time: " << elapsed.count() / 10000.0 / (double)iterations << "ms" << std::endl;
}

#ifdef _WIN64
#define PYTHIA_DLL "Pythia_x64.dll"
#define FUNCNAME "RVExtension"
#else
#define PYTHIA_DLL "Pythia.dll"
#define FUNCNAME "_RVExtension@12"
#endif

int main()
{
    HINSTANCE hInstLibrary = LoadLibrary(TEXT(PYTHIA_DLL));

    if (hInstLibrary)
    {
        RVExtension = (RVExtension_t)GetProcAddress(hInstLibrary, FUNCNAME);

        if (RVExtension)
        {
            test();
        }
        else
        {
            std::cout << "Could not get RVExtension function." << std::endl;
        }
        FreeLibrary(hInstLibrary);
    }
    else
    {
        std::cout << "Could not open library dll." << std::endl;
    }

    std::cout << "Press enter to continue...";
    std::cin.get();
    return 0;
}

<|endoftext|>


<commit_before>//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to GAS-format SPARC assembly language.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "asm-printer"
#include "Sparc.h"
#include "SparcInstrInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
#include <cstring>
#include <map>
using namespace llvm;

STATISTIC(EmittedInsts, "Number of machine instrs printed");

namespace {
  struct VISIBILITY_HIDDEN SparcAsmPrinter : public AsmPrinter {
    SparcAsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
      : AsmPrinter(O, TM, T) {
    }

    /// We name each basic block in a Function with a unique number, so
    /// that we can consistently refer to them later. This is cleared
    /// at the beginning of each call to runOnMachineFunction().
    ///
    typedef std::map<const Value *, unsigned> ValueMapTy;
    ValueMapTy NumberForBB;

    virtual const char *getPassName() const {
      return "Sparc Assembly Printer";
    }

    void printModuleLevelGV(const GlobalVariable* GVar);
    void printOperand(const MachineInstr *MI, int opNum);
    void printMemOperand(const MachineInstr *MI, int opNum,
                         const char *Modifier = 0);
    void printCCOperand(const MachineInstr *MI, int opNum);

    bool printInstruction(const MachineInstr *MI);  // autogenerated.
    bool runOnMachineFunction(MachineFunction &F);
    bool doInitialization(Module &M);
    bool doFinalization(Module &M);
  };
} // end of anonymous namespace

#include "SparcGenAsmWriter.inc"

/// createSparcCodePrinterPass - Returns a pass that prints the SPARC
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description.  This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *llvm::createSparcCodePrinterPass(raw_ostream &o,
                                               TargetMachine &tm) {
  return new SparcAsmPrinter(o, tm, tm.getTargetAsmInfo());
}

/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  SetupMachineFunction(MF);

  // Print out constants referenced by the function
  EmitConstantPool(MF.getConstantPool());

  // BBNumber is used here so that a given Printer will never give two
  // BBs the same name. (If you have a better way, please let me know!)
  static unsigned BBNumber = 0;

  O << "\n\n";
  // What's my mangled name?
  CurrentFnName = Mang->getValueName(MF.getFunction());

  // Print out the label for the function.
  const Function *F = MF.getFunction();
  SwitchToSection(TAI->SectionForGlobal(F));
  EmitAlignment(4, F);
  O << "\t.globl\t" << CurrentFnName << '\n';

  printVisibility(CurrentFnName, F->getVisibility());

  O << "\t.type\t" << CurrentFnName << ", #function\n";
  O << CurrentFnName << ":\n";

  // Number each basic block so that we can consistently refer to them
  // in PC-relative references.
  // FIXME: Why not use the MBB numbers?
  NumberForBB.clear();
  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
       I != E; ++I) {
    NumberForBB[I->getBasicBlock()] = BBNumber++;
  }

  // Print out code for the function.
  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
       I != E; ++I) {
    // Print a label for the basic block.
    if (I != MF.begin()) {
      printBasicBlockLabel(I, true, true);
      O << '\n';
    }
    for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
         II != E; ++II) {
      // Print the assembly for the instruction.
      printInstruction(II);
      ++EmittedInsts;
    }
  }

  // We didn't modify anything.
  return false;
}

void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
  const MachineOperand &MO = MI->getOperand (opNum);
  const TargetRegisterInfo &RI = *TM.getRegisterInfo();
  bool CloseParen = false;
  if (MI->getOpcode() == SP::SETHIi && !MO.isReg() && !MO.isImm()) {
    O << "%hi(";
    CloseParen = true;
  } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri) &&
             !MO.isReg() && !MO.isImm()) {
    O << "%lo(";
    CloseParen = true;
  }
  switch (MO.getType()) {
  case MachineOperand::MO_Register:
    if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
      O << "%" << LowercaseString (RI.get(MO.getReg()).AsmName);
    else
      O << "%reg" << MO.getReg();
    break;

  case MachineOperand::MO_Immediate:
    O << (int)MO.getImm();
    break;
  case MachineOperand::MO_MachineBasicBlock:
    printBasicBlockLabel(MO.getMBB());
    return;
  case MachineOperand::MO_GlobalAddress:
    O << Mang->getValueName(MO.getGlobal());
    break;
  case MachineOperand::MO_ExternalSymbol:
    O << MO.getSymbolName();
    break;
  case MachineOperand::MO_ConstantPoolIndex:
    O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
      << MO.getIndex();
    break;
  default:
    O << "<unknown operand type>"; abort (); break;
  }
  if (CloseParen) O << ")";
}

void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
                                      const char *Modifier) {
  printOperand(MI, opNum);

  // If this is an ADD operand, emit it like normal operands.
  if (Modifier && !strcmp(Modifier, "arith")) {
    O << ", ";
    printOperand(MI, opNum+1);
    return;
  }

  if (MI->getOperand(opNum+1).isReg() &&
      MI->getOperand(opNum+1).getReg() == SP::G0)
    return;   // don't print "+%g0"
  if (MI->getOperand(opNum+1).isImm() &&
      MI->getOperand(opNum+1).getImm() == 0)
    return;   // don't print "+0"

  O << "+";
  if (MI->getOperand(opNum+1).isGlobal() ||
      MI->getOperand(opNum+1).isCPI()) {
    O << "%lo(";
    printOperand(MI, opNum+1);
    O << ")";
  } else {
    printOperand(MI, opNum+1);
  }
}

void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
  int CC = (int)MI->getOperand(opNum).getImm();
  O << SPARCCondCodeToString((SPCC::CondCodes)CC);
}

bool SparcAsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M);
  return false; // success
}

bool SparcAsmPrinter::doFinalization(Module &M) {
  // Print out module-level global variables here.
  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I)
    printModuleLevelGV(I);

  O << '\n';

  return AsmPrinter::doFinalization(M);
}

void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
  const TargetData *TD = TM.getTargetData();

  if (!GVar->hasInitializer())
    return;  // External global require no code

  // Check to see if this is a special global used by LLVM, if so, emit it.
  if (EmitSpecialLLVMGlobal(GVar))
    return;

  O << "\n\n";
  std::string name = Mang->getValueName(GVar);
  Constant *C = GVar->getInitializer();
  unsigned Size = TD->getABITypeSize(C->getType());
  unsigned Align = TD->getPreferredAlignment(GVar);

  printVisibility(name, GVar->getVisibility());

  SwitchToSection(TAI->SectionForGlobal(GVar));

  if (C->isNullValue() && !GVar->hasSection()) {
    if (!GVar->isThreadLocal() &&
        (GVar->hasInternalLinkage() || GVar->mayBeOverridden())) {
      if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.

      if (GVar->hasInternalLinkage())
        O << "\t.local " << name << '\n';

      O << TAI->getCOMMDirective() << name << ',' << Size;
      if (TAI->getCOMMDirectiveTakesAlignment())
        O << ',' << (1 << Align);

      O << '\n';
      return;
    }
  }

  switch (GVar->getLinkage()) {
   case GlobalValue::CommonLinkage:
   case GlobalValue::LinkOnceLinkage:
   case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
    // Nonnull linkonce -> weak
    O << "\t.weak " << name << '\n';
    break;
   case GlobalValue::AppendingLinkage:
    // FIXME: appending linkage variables should go into a section of
    // their name or something.  For now, just emit them as external.
   case GlobalValue::ExternalLinkage:
    // If external or appending, declare as a global symbol
    O << TAI->getGlobalDirective() << name << '\n';
    // FALL THROUGH
   case GlobalValue::InternalLinkage:
    break;
   case GlobalValue::GhostLinkage:
    cerr << "Should not have any unmaterialized functions!\n";
    abort();
   case GlobalValue::DLLImportLinkage:
    cerr << "DLLImport linkage is not supported by this target!\n";
    abort();
   case GlobalValue::DLLExportLinkage:
    cerr << "DLLExport linkage is not supported by this target!\n";
    abort();
   default:
    assert(0 && "Unknown linkage type!");
  }

  EmitAlignment(Align, GVar);

  if (TAI->hasDotTypeDotSizeDirective()) {
    O << "\t.type " << name << ",#object\n";
    O << "\t.size " << name << ',' << Size << '\n';
  }

  O << name << ":\n";
  EmitGlobalConstant(C);
}
<commit_msg>Add rudimentary asmprinter support for printing inline asm operands for sparc.<commit_after>//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to GAS-format SPARC assembly language.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "asm-printer"
#include "Sparc.h"
#include "SparcInstrInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
#include <cstring>
#include <map>
using namespace llvm;

STATISTIC(EmittedInsts, "Number of machine instrs printed");

namespace {
  struct VISIBILITY_HIDDEN SparcAsmPrinter : public AsmPrinter {
    SparcAsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
      : AsmPrinter(O, TM, T) {
    }

    /// We name each basic block in a Function with a unique number, so
    /// that we can consistently refer to them later. This is cleared
    /// at the beginning of each call to runOnMachineFunction().
    ///
    typedef std::map<const Value *, unsigned> ValueMapTy;
    ValueMapTy NumberForBB;

    virtual const char *getPassName() const {
      return "Sparc Assembly Printer";
    }

    void printModuleLevelGV(const GlobalVariable* GVar);
    void printOperand(const MachineInstr *MI, int opNum);
    void printMemOperand(const MachineInstr *MI, int opNum,
                         const char *Modifier = 0);
    void printCCOperand(const MachineInstr *MI, int opNum);

    bool printInstruction(const MachineInstr *MI);  // autogenerated.
    bool runOnMachineFunction(MachineFunction &F);
    bool doInitialization(Module &M);
    bool doFinalization(Module &M);
    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                       unsigned AsmVariant, const char *ExtraCode);
    bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                             unsigned AsmVariant, const char *ExtraCode);
  };
} // end of anonymous namespace

#include "SparcGenAsmWriter.inc"

/// createSparcCodePrinterPass - Returns a pass that prints the SPARC
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description.  This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *llvm::createSparcCodePrinterPass(raw_ostream &o,
                                               TargetMachine &tm) {
  return new SparcAsmPrinter(o, tm, tm.getTargetAsmInfo());
}

/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  SetupMachineFunction(MF);

  // Print out constants referenced by the function
  EmitConstantPool(MF.getConstantPool());

  // BBNumber is used here so that a given Printer will never give two
  // BBs the same name. (If you have a better way, please let me know!)
  static unsigned BBNumber = 0;

  O << "\n\n";
  // What's my mangled name?
  CurrentFnName = Mang->getValueName(MF.getFunction());

  // Print out the label for the function.
  const Function *F = MF.getFunction();
  SwitchToSection(TAI->SectionForGlobal(F));
  EmitAlignment(4, F);
  O << "\t.globl\t" << CurrentFnName << '\n';

  printVisibility(CurrentFnName, F->getVisibility());

  O << "\t.type\t" << CurrentFnName << ", #function\n";
  O << CurrentFnName << ":\n";

  // Number each basic block so that we can consistently refer to them
  // in PC-relative references.
  // FIXME: Why not use the MBB numbers?
  NumberForBB.clear();
  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
       I != E; ++I) {
    NumberForBB[I->getBasicBlock()] = BBNumber++;
  }

  // Print out code for the function.
  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
       I != E; ++I) {
    // Print a label for the basic block.
    if (I != MF.begin()) {
      printBasicBlockLabel(I, true, true);
      O << '\n';
    }
    for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
         II != E; ++II) {
      // Print the assembly for the instruction.
      printInstruction(II);
      ++EmittedInsts;
    }
  }

  // We didn't modify anything.
  return false;
}

void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
  const MachineOperand &MO = MI->getOperand (opNum);
  const TargetRegisterInfo &RI = *TM.getRegisterInfo();
  bool CloseParen = false;
  if (MI->getOpcode() == SP::SETHIi && !MO.isReg() && !MO.isImm()) {
    O << "%hi(";
    CloseParen = true;
  } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri) &&
             !MO.isReg() && !MO.isImm()) {
    O << "%lo(";
    CloseParen = true;
  }
  switch (MO.getType()) {
  case MachineOperand::MO_Register:
    if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
      O << "%" << LowercaseString (RI.get(MO.getReg()).AsmName);
    else
      O << "%reg" << MO.getReg();
    break;

  case MachineOperand::MO_Immediate:
    O << (int)MO.getImm();
    break;
  case MachineOperand::MO_MachineBasicBlock:
    printBasicBlockLabel(MO.getMBB());
    return;
  case MachineOperand::MO_GlobalAddress:
    O << Mang->getValueName(MO.getGlobal());
    break;
  case MachineOperand::MO_ExternalSymbol:
    O << MO.getSymbolName();
    break;
  case MachineOperand::MO_ConstantPoolIndex:
    O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
      << MO.getIndex();
    break;
  default:
    O << "<unknown operand type>"; abort (); break;
  }
  if (CloseParen) O << ")";
}

void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
                                      const char *Modifier) {
  printOperand(MI, opNum);

  // If this is an ADD operand, emit it like normal operands.
  if (Modifier && !strcmp(Modifier, "arith")) {
    O << ", ";
    printOperand(MI, opNum+1);
    return;
  }

  if (MI->getOperand(opNum+1).isReg() &&
      MI->getOperand(opNum+1).getReg() == SP::G0)
    return;   // don't print "+%g0"
  if (MI->getOperand(opNum+1).isImm() &&
      MI->getOperand(opNum+1).getImm() == 0)
    return;   // don't print "+0"

  O << "+";
  if (MI->getOperand(opNum+1).isGlobal() ||
      MI->getOperand(opNum+1).isCPI()) {
    O << "%lo(";
    printOperand(MI, opNum+1);
    O << ")";
  } else {
    printOperand(MI, opNum+1);
  }
}

void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
  int CC = (int)MI->getOperand(opNum).getImm();
  O << SPARCCondCodeToString((SPCC::CondCodes)CC);
}

bool SparcAsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M);
  return false; // success
}

bool SparcAsmPrinter::doFinalization(Module &M) {
  // Print out module-level global variables here.
  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I)
    printModuleLevelGV(I);

  O << '\n';

  return AsmPrinter::doFinalization(M);
}

void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
  const TargetData *TD = TM.getTargetData();

  if (!GVar->hasInitializer())
    return;  // External global require no code

  // Check to see if this is a special global used by LLVM, if so, emit it.
  if (EmitSpecialLLVMGlobal(GVar))
    return;

  O << "\n\n";
  std::string name = Mang->getValueName(GVar);
  Constant *C = GVar->getInitializer();
  unsigned Size = TD->getABITypeSize(C->getType());
  unsigned Align = TD->getPreferredAlignment(GVar);

  printVisibility(name, GVar->getVisibility());

  SwitchToSection(TAI->SectionForGlobal(GVar));

  if (C->isNullValue() && !GVar->hasSection()) {
    if (!GVar->isThreadLocal() &&
        (GVar->hasInternalLinkage() || GVar->mayBeOverridden())) {
      if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.

      if (GVar->hasInternalLinkage())
        O << "\t.local " << name << '\n';

      O << TAI->getCOMMDirective() << name << ',' << Size;
      if (TAI->getCOMMDirectiveTakesAlignment())
        O << ',' << (1 << Align);

      O << '\n';
      return;
    }
  }

  switch (GVar->getLinkage()) {
   case GlobalValue::CommonLinkage:
   case GlobalValue::LinkOnceLinkage:
   case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
    // Nonnull linkonce -> weak
    O << "\t.weak " << name << '\n';
    break;
   case GlobalValue::AppendingLinkage:
    // FIXME: appending linkage variables should go into a section of
    // their name or something.  For now, just emit them as external.
   case GlobalValue::ExternalLinkage:
    // If external or appending, declare as a global symbol
    O << TAI->getGlobalDirective() << name << '\n';
    // FALL THROUGH
   case GlobalValue::InternalLinkage:
    break;
   case GlobalValue::GhostLinkage:
    cerr << "Should not have any unmaterialized functions!\n";
    abort();
   case GlobalValue::DLLImportLinkage:
    cerr << "DLLImport linkage is not supported by this target!\n";
    abort();
   case GlobalValue::DLLExportLinkage:
    cerr << "DLLExport linkage is not supported by this target!\n";
    abort();
   default:
    assert(0 && "Unknown linkage type!");
  }

  EmitAlignment(Align, GVar);

  if (TAI->hasDotTypeDotSizeDirective()) {
    O << "\t.type " << name << ",#object\n";
    O << "\t.size " << name << ',' << Size << '\n';
  }

  O << name << ":\n";
  EmitGlobalConstant(C);
}

/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                                      unsigned AsmVariant,
                                      const char *ExtraCode) {
  if (ExtraCode && ExtraCode[0])
    return true;  // Unknown modifier

  printOperand(MI, OpNo);

  return false;
}

bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
                                            unsigned OpNo,
                                            unsigned AsmVariant,
                                            const char *ExtraCode) {
  if (ExtraCode && ExtraCode[0])
    return true;  // Unknown modifier

  O << '[';
  printMemOperand(MI, OpNo);
  O << ']';

  return false;
}
<|endoftext|>


<commit_before>//===- FunctionAttrs.cpp - Pass which marks functions readnone or readonly ===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a simple interprocedural pass which walks the
// call-graph, looking for functions which do not access or only read
// non-local memory, and marking them readnone/readonly.  In addition,
// it marks function arguments (of pointer type) 'nocapture' if a call
// to the function does not create any copies of the pointer value that
// outlive the call.  This more or less means that the pointer is only
// dereferenced, and not returned from the function or stored in a global.
// This pass is implemented as a bottom-up traversal of the call-graph.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "functionattrs"
#include "llvm/Transforms/IPO.h"
#include "llvm/CallGraphSCCPass.h"
#include "llvm/GlobalVariable.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/MallocHelper.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/UniqueVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/InstIterator.h"
using namespace llvm;

STATISTIC(NumReadNone, "Number of functions marked readnone");
STATISTIC(NumReadOnly, "Number of functions marked readonly");
STATISTIC(NumNoCapture, "Number of arguments marked nocapture");
STATISTIC(NumNoAlias, "Number of function returns marked noalias");

namespace {
  struct VISIBILITY_HIDDEN FunctionAttrs : public CallGraphSCCPass {
    static char ID; // Pass identification, replacement for typeid
    FunctionAttrs() : CallGraphSCCPass(&ID) {}

    // runOnSCC - Analyze the SCC, performing the transformation if possible.
    bool runOnSCC(std::vector<CallGraphNode *> &SCC);

    // AddReadAttrs - Deduce readonly/readnone attributes for the SCC.
    bool AddReadAttrs(const std::vector<CallGraphNode *> &SCC);

    // AddNoCaptureAttrs - Deduce nocapture attributes for the SCC.
    bool AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC);

    // IsFunctionMallocLike - Does this function allocate new memory?
    bool IsFunctionMallocLike(Function *F,
                              SmallPtrSet<Function*, 8> &) const;

    // AddNoAliasAttrs - Deduce noalias attributes for the SCC.
    bool AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      CallGraphSCCPass::getAnalysisUsage(AU);
    }

    bool PointsToLocalMemory(Value *V);
  };
}

char FunctionAttrs::ID = 0;
static RegisterPass<FunctionAttrs>
X("functionattrs", "Deduce function attributes");

Pass *llvm::createFunctionAttrsPass() { return new FunctionAttrs(); }

/// PointsToLocalMemory - Returns whether the given pointer value points to
/// memory that is local to the function.  Global constants are considered
/// local to all functions.
bool FunctionAttrs::PointsToLocalMemory(Value *V) {
  V = V->getUnderlyingObject();
  // An alloca instruction defines local memory.
  if (isa<AllocaInst>(V))
    return true;
  // A global constant counts as local memory for our purposes.
  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
    return GV->isConstant();
  // Could look through phi nodes and selects here, but it doesn't seem
  // to be useful in practice.
  return false;
}

/// AddReadAttrs - Deduce readonly/readnone attributes for the SCC.
bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &SCC) {
  SmallPtrSet<Function*, 8> SCCNodes;

  // Fill SCCNodes with the elements of the SCC.  Used for quickly
  // looking up whether a given CallGraphNode is in this SCC.
  for (unsigned i = 0, e = SCC.size(); i != e; ++i)
    SCCNodes.insert(SCC[i]->getFunction());

  // Check if any of the functions in the SCC read or write memory.  If they
  // write memory then they can't be marked readnone or readonly.
  bool ReadsMemory = false;
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();

    if (F == 0)
      // External node - may write memory.  Just give up.
      return false;

    if (F->doesNotAccessMemory())
      // Already perfect!
      continue;

    // Definitions with weak linkage may be overridden at linktime with
    // something that writes memory, so treat them like declarations.
    if (F->isDeclaration() || F->mayBeOverridden()) {
      if (!F->onlyReadsMemory())
        // May write memory.  Just give up.
        return false;

      ReadsMemory = true;
      continue;
    }

    // Scan the function body for instructions that may read or write memory.
    for (inst_iterator II = inst_begin(F), E = inst_end(F); II != E; ++II) {
      Instruction *I = &*II;

      // Some instructions can be ignored even if they read or write memory.
      // Detect these now, skipping to the next instruction if one is found.
      CallSite CS = CallSite::get(I);
      if (CS.getInstruction() && CS.getCalledFunction()) {
        // Ignore calls to functions in the same SCC.
        if (SCCNodes.count(CS.getCalledFunction()))
          continue;
      } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
        // Ignore loads from local memory.
        if (PointsToLocalMemory(LI->getPointerOperand()))
          continue;
      } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
        // Ignore stores to local memory.
        if (PointsToLocalMemory(SI->getPointerOperand()))
          continue;
      }

      // Any remaining instructions need to be taken seriously!  Check if they
      // read or write memory.
      if (I->mayWriteToMemory())
        // Writes memory.  Just give up.
        return false;

      if (isa<MallocInst>(I))
        // malloc claims not to write memory!  PR3754.
        return false;

      // If this instruction may read memory, remember that.
      ReadsMemory |= I->mayReadFromMemory();
    }
  }

  // Success!  Functions in this SCC do not access memory, or only read memory.
  // Give them the appropriate attribute.
  bool MadeChange = false;
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();

    if (F->doesNotAccessMemory())
      // Already perfect!
      continue;

    if (F->onlyReadsMemory() && ReadsMemory)
      // No change.
      continue;

    MadeChange = true;

    // Clear out any existing attributes.
    F->removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone);

    // Add in the new attribute.
    F->addAttribute(~0, ReadsMemory? Attribute::ReadOnly : Attribute::ReadNone);

    if (ReadsMemory)
      ++NumReadOnly;
    else
      ++NumReadNone;
  }

  return MadeChange;
}

/// AddNoCaptureAttrs - Deduce nocapture attributes for the SCC.
bool FunctionAttrs::AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC) {
  bool Changed = false;

  // Check each function in turn, determining which pointer arguments are not
  // captured.
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();

    if (F == 0)
      // External node - skip it;
      continue;

    // Definitions with weak linkage may be overridden at linktime with
    // something that writes memory, so treat them like declarations.
    if (F->isDeclaration() || F->mayBeOverridden())
      continue;

    for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A!=E; ++A)
      if (isa<PointerType>(A->getType()) && !A->hasNoCaptureAttr() &&
          !PointerMayBeCaptured(A, true)) {
        A->addAttr(Attribute::NoCapture);
        ++NumNoCapture;
        Changed = true;
      }
  }

  return Changed;
}

/// IsFunctionMallocLike - A function is malloc-like if it returns either null
/// or a pointer that doesn't alias any other pointer visible to the caller.
bool FunctionAttrs::IsFunctionMallocLike(Function *F,
                              SmallPtrSet<Function*, 8> &SCCNodes) const {
  UniqueVector<Value *> FlowsToReturn;
  for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I)
    if (ReturnInst *Ret = dyn_cast<ReturnInst>(I->getTerminator()))
      FlowsToReturn.insert(Ret->getReturnValue());

  for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {
    Value *RetVal = FlowsToReturn[i+1];   // UniqueVector[0] is reserved.

    if (Constant *C = dyn_cast<Constant>(RetVal)) {
      if (!C->isNullValue() && !isa<UndefValue>(C))
        return false;

      continue;
    }

    if (isa<Argument>(RetVal))
      return false;

    if (Instruction *RVI = dyn_cast<Instruction>(RetVal))
      switch (RVI->getOpcode()) {
        // Extend the analysis by looking upwards.
        case Instruction::BitCast:
          if (isMalloc(RVI))
            break;
          // fall through
        case Instruction::GetElementPtr:
          FlowsToReturn.insert(RVI->getOperand(0));
          continue;
        case Instruction::Select: {
          SelectInst *SI = cast<SelectInst>(RVI);
          FlowsToReturn.insert(SI->getTrueValue());
          FlowsToReturn.insert(SI->getFalseValue());
        } continue;
        case Instruction::PHI: {
          PHINode *PN = cast<PHINode>(RVI);
          for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
            FlowsToReturn.insert(PN->getIncomingValue(i));
        } continue;

        // Check whether the pointer came from an allocation.
        case Instruction::Alloca:
        case Instruction::Malloc:
          break;
        case Instruction::Call:
          if (isMalloc(RVI))
            break;
        case Instruction::Invoke: {
          CallSite CS(RVI);
          if (CS.paramHasAttr(0, Attribute::NoAlias))
            break;
          if (CS.getCalledFunction() &&
              SCCNodes.count(CS.getCalledFunction()))
            break;
        } // fall-through
        default:
          return false;  // Did not come from an allocation.
      }

    if (PointerMayBeCaptured(RetVal, false))
      return false;
  }

  return true;
}

/// AddNoAliasAttrs - Deduce noalias attributes for the SCC.
bool FunctionAttrs::AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC) {
  SmallPtrSet<Function*, 8> SCCNodes;

  // Fill SCCNodes with the elements of the SCC.  Used for quickly
  // looking up whether a given CallGraphNode is in this SCC.
  for (unsigned i = 0, e = SCC.size(); i != e; ++i)
    SCCNodes.insert(SCC[i]->getFunction());

  // Check each function in turn, determining which functions return noalias
  // pointers.
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();

    if (F == 0)
      // External node - skip it;
      return false;

    // Already noalias.
    if (F->doesNotAlias(0))
      continue;

    // Definitions with weak linkage may be overridden at linktime, so
    // treat them like declarations.
    if (F->isDeclaration() || F->mayBeOverridden())
      return false;

    // We annotate noalias return values, which are only applicable to
    // pointer types.
    if (!isa<PointerType>(F->getReturnType()))
      continue;

    if (!IsFunctionMallocLike(F, SCCNodes))
      return false;
  }

  bool MadeChange = false;
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();
    if (F->doesNotAlias(0) || !isa<PointerType>(F->getReturnType()))
      continue;

    F->setDoesNotAlias(0);
    ++NumNoAlias;
    MadeChange = true;
  }

  return MadeChange;
}

bool FunctionAttrs::runOnSCC(std::vector<CallGraphNode *> &SCC) {
  bool Changed = AddReadAttrs(SCC);
  Changed |= AddNoCaptureAttrs(SCC);
  Changed |= AddNoAliasAttrs(SCC);
  return Changed;
}
<commit_msg>remove special handling of bitcast(malloc), it will be handled when the loop inspects the bitcast operand.<commit_after>//===- FunctionAttrs.cpp - Pass which marks functions readnone or readonly ===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a simple interprocedural pass which walks the
// call-graph, looking for functions which do not access or only read
// non-local memory, and marking them readnone/readonly.  In addition,
// it marks function arguments (of pointer type) 'nocapture' if a call
// to the function does not create any copies of the pointer value that
// outlive the call.  This more or less means that the pointer is only
// dereferenced, and not returned from the function or stored in a global.
// This pass is implemented as a bottom-up traversal of the call-graph.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "functionattrs"
#include "llvm/Transforms/IPO.h"
#include "llvm/CallGraphSCCPass.h"
#include "llvm/GlobalVariable.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/MallocHelper.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/UniqueVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/InstIterator.h"
using namespace llvm;

STATISTIC(NumReadNone, "Number of functions marked readnone");
STATISTIC(NumReadOnly, "Number of functions marked readonly");
STATISTIC(NumNoCapture, "Number of arguments marked nocapture");
STATISTIC(NumNoAlias, "Number of function returns marked noalias");

namespace {
  struct VISIBILITY_HIDDEN FunctionAttrs : public CallGraphSCCPass {
    static char ID; // Pass identification, replacement for typeid
    FunctionAttrs() : CallGraphSCCPass(&ID) {}

    // runOnSCC - Analyze the SCC, performing the transformation if possible.
    bool runOnSCC(std::vector<CallGraphNode *> &SCC);

    // AddReadAttrs - Deduce readonly/readnone attributes for the SCC.
    bool AddReadAttrs(const std::vector<CallGraphNode *> &SCC);

    // AddNoCaptureAttrs - Deduce nocapture attributes for the SCC.
    bool AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC);

    // IsFunctionMallocLike - Does this function allocate new memory?
    bool IsFunctionMallocLike(Function *F,
                              SmallPtrSet<Function*, 8> &) const;

    // AddNoAliasAttrs - Deduce noalias attributes for the SCC.
    bool AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      CallGraphSCCPass::getAnalysisUsage(AU);
    }

    bool PointsToLocalMemory(Value *V);
  };
}

char FunctionAttrs::ID = 0;
static RegisterPass<FunctionAttrs>
X("functionattrs", "Deduce function attributes");

Pass *llvm::createFunctionAttrsPass() { return new FunctionAttrs(); }

/// PointsToLocalMemory - Returns whether the given pointer value points to
/// memory that is local to the function.  Global constants are considered
/// local to all functions.
bool FunctionAttrs::PointsToLocalMemory(Value *V) {
  V = V->getUnderlyingObject();
  // An alloca instruction defines local memory.
  if (isa<AllocaInst>(V))
    return true;
  // A global constant counts as local memory for our purposes.
  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
    return GV->isConstant();
  // Could look through phi nodes and selects here, but it doesn't seem
  // to be useful in practice.
  return false;
}

/// AddReadAttrs - Deduce readonly/readnone attributes for the SCC.
bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &SCC) {
  SmallPtrSet<Function*, 8> SCCNodes;

  // Fill SCCNodes with the elements of the SCC.  Used for quickly
  // looking up whether a given CallGraphNode is in this SCC.
  for (unsigned i = 0, e = SCC.size(); i != e; ++i)
    SCCNodes.insert(SCC[i]->getFunction());

  // Check if any of the functions in the SCC read or write memory.  If they
  // write memory then they can't be marked readnone or readonly.
  bool ReadsMemory = false;
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();

    if (F == 0)
      // External node - may write memory.  Just give up.
      return false;

    if (F->doesNotAccessMemory())
      // Already perfect!
      continue;

    // Definitions with weak linkage may be overridden at linktime with
    // something that writes memory, so treat them like declarations.
    if (F->isDeclaration() || F->mayBeOverridden()) {
      if (!F->onlyReadsMemory())
        // May write memory.  Just give up.
        return false;

      ReadsMemory = true;
      continue;
    }

    // Scan the function body for instructions that may read or write memory.
    for (inst_iterator II = inst_begin(F), E = inst_end(F); II != E; ++II) {
      Instruction *I = &*II;

      // Some instructions can be ignored even if they read or write memory.
      // Detect these now, skipping to the next instruction if one is found.
      CallSite CS = CallSite::get(I);
      if (CS.getInstruction() && CS.getCalledFunction()) {
        // Ignore calls to functions in the same SCC.
        if (SCCNodes.count(CS.getCalledFunction()))
          continue;
      } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
        // Ignore loads from local memory.
        if (PointsToLocalMemory(LI->getPointerOperand()))
          continue;
      } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
        // Ignore stores to local memory.
        if (PointsToLocalMemory(SI->getPointerOperand()))
          continue;
      }

      // Any remaining instructions need to be taken seriously!  Check if they
      // read or write memory.
      if (I->mayWriteToMemory())
        // Writes memory.  Just give up.
        return false;

      if (isa<MallocInst>(I))
        // malloc claims not to write memory!  PR3754.
        return false;

      // If this instruction may read memory, remember that.
      ReadsMemory |= I->mayReadFromMemory();
    }
  }

  // Success!  Functions in this SCC do not access memory, or only read memory.
  // Give them the appropriate attribute.
  bool MadeChange = false;
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();

    if (F->doesNotAccessMemory())
      // Already perfect!
      continue;

    if (F->onlyReadsMemory() && ReadsMemory)
      // No change.
      continue;

    MadeChange = true;

    // Clear out any existing attributes.
    F->removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone);

    // Add in the new attribute.
    F->addAttribute(~0, ReadsMemory? Attribute::ReadOnly : Attribute::ReadNone);

    if (ReadsMemory)
      ++NumReadOnly;
    else
      ++NumReadNone;
  }

  return MadeChange;
}

/// AddNoCaptureAttrs - Deduce nocapture attributes for the SCC.
bool FunctionAttrs::AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC) {
  bool Changed = false;

  // Check each function in turn, determining which pointer arguments are not
  // captured.
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();

    if (F == 0)
      // External node - skip it;
      continue;

    // Definitions with weak linkage may be overridden at linktime with
    // something that writes memory, so treat them like declarations.
    if (F->isDeclaration() || F->mayBeOverridden())
      continue;

    for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A!=E; ++A)
      if (isa<PointerType>(A->getType()) && !A->hasNoCaptureAttr() &&
          !PointerMayBeCaptured(A, true)) {
        A->addAttr(Attribute::NoCapture);
        ++NumNoCapture;
        Changed = true;
      }
  }

  return Changed;
}

/// IsFunctionMallocLike - A function is malloc-like if it returns either null
/// or a pointer that doesn't alias any other pointer visible to the caller.
bool FunctionAttrs::IsFunctionMallocLike(Function *F,
                              SmallPtrSet<Function*, 8> &SCCNodes) const {
  UniqueVector<Value *> FlowsToReturn;
  for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I)
    if (ReturnInst *Ret = dyn_cast<ReturnInst>(I->getTerminator()))
      FlowsToReturn.insert(Ret->getReturnValue());

  for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {
    Value *RetVal = FlowsToReturn[i+1];   // UniqueVector[0] is reserved.

    if (Constant *C = dyn_cast<Constant>(RetVal)) {
      if (!C->isNullValue() && !isa<UndefValue>(C))
        return false;

      continue;
    }

    if (isa<Argument>(RetVal))
      return false;

    if (Instruction *RVI = dyn_cast<Instruction>(RetVal))
      switch (RVI->getOpcode()) {
        // Extend the analysis by looking upwards.
        case Instruction::BitCast:
        case Instruction::GetElementPtr:
          FlowsToReturn.insert(RVI->getOperand(0));
          continue;
        case Instruction::Select: {
          SelectInst *SI = cast<SelectInst>(RVI);
          FlowsToReturn.insert(SI->getTrueValue());
          FlowsToReturn.insert(SI->getFalseValue());
          continue;
        }
        case Instruction::PHI: {
          PHINode *PN = cast<PHINode>(RVI);
          for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
            FlowsToReturn.insert(PN->getIncomingValue(i));
          continue;
        }

        // Check whether the pointer came from an allocation.
        case Instruction::Alloca:
        case Instruction::Malloc:
          break;
        case Instruction::Call:
          if (isMalloc(RVI))
            break;
        case Instruction::Invoke: {
          CallSite CS(RVI);
          if (CS.paramHasAttr(0, Attribute::NoAlias))
            break;
          if (CS.getCalledFunction() &&
              SCCNodes.count(CS.getCalledFunction()))
            break;
        } // fall-through
        default:
          return false;  // Did not come from an allocation.
      }

    if (PointerMayBeCaptured(RetVal, false))
      return false;
  }

  return true;
}

/// AddNoAliasAttrs - Deduce noalias attributes for the SCC.
bool FunctionAttrs::AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC) {
  SmallPtrSet<Function*, 8> SCCNodes;

  // Fill SCCNodes with the elements of the SCC.  Used for quickly
  // looking up whether a given CallGraphNode is in this SCC.
  for (unsigned i = 0, e = SCC.size(); i != e; ++i)
    SCCNodes.insert(SCC[i]->getFunction());

  // Check each function in turn, determining which functions return noalias
  // pointers.
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();

    if (F == 0)
      // External node - skip it;
      return false;

    // Already noalias.
    if (F->doesNotAlias(0))
      continue;

    // Definitions with weak linkage may be overridden at linktime, so
    // treat them like declarations.
    if (F->isDeclaration() || F->mayBeOverridden())
      return false;

    // We annotate noalias return values, which are only applicable to
    // pointer types.
    if (!isa<PointerType>(F->getReturnType()))
      continue;

    if (!IsFunctionMallocLike(F, SCCNodes))
      return false;
  }

  bool MadeChange = false;
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();
    if (F->doesNotAlias(0) || !isa<PointerType>(F->getReturnType()))
      continue;

    F->setDoesNotAlias(0);
    ++NumNoAlias;
    MadeChange = true;
  }

  return MadeChange;
}

bool FunctionAttrs::runOnSCC(std::vector<CallGraphNode *> &SCC) {
  bool Changed = AddReadAttrs(SCC);
  Changed |= AddNoCaptureAttrs(SCC);
  Changed |= AddNoAliasAttrs(SCC);
  return Changed;
}
<|endoftext|>


<commit_before><commit_msg>added support to save nr of points in search results<commit_after><|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2008 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

/**
  \file    GLVolume2DTex.cpp
  \author  Jens Krueger
           DFKI Saarbruecken & SCI Institute University of Utah
  \date    May 2010
*/

#include "GLVolume2DTex.h"
#include "GLTexture2D.h"
#include <cstring> // for memcpy

using namespace tuvok;
using namespace std;

GLVolume2DTex::GLVolume2DTex(UINT32 iSizeX, UINT32 iSizeY, UINT32 iSizeZ,
                             GLint internalformat, GLenum format, GLenum type,
                             UINT32 iSizePerElement,
                             const GLvoid *voxels,
                             GLint iMagFilter,
                             GLint iMinFilter,
                             GLint wrapX,
                             GLint wrapY,
                             GLint wrapZ) :
      m_iSizeX(iSizeX),
      m_iSizeY(iSizeY),
      m_iSizeZ(iSizeZ),
      m_internalformat(internalformat),
      m_format(format),
      m_type(type),
      m_iSizePerElement(iSizePerElement),
      m_iMagFilter(iMagFilter),
      m_iMinFilter(iMinFilter),
      m_wrapX(wrapX),
      m_wrapY(wrapY),
      m_wrapZ(wrapZ),
      m_iGPUSize(0),
      m_iCPUSize(0)
{
  m_pTextures.resize(3);
  CreateGLResources();
  SetData(voxels);
}

GLVolume2DTex::GLVolume2DTex() :
      m_iSizeX(0),
      m_iSizeY(0),
      m_iSizeZ(0),
      m_internalformat(0),
      m_format(0),
      m_type(0),
      m_iSizePerElement(0),
      m_iMagFilter(GL_NEAREST),
      m_iMinFilter(GL_NEAREST),
      m_wrapX(GL_CLAMP_TO_EDGE),
      m_wrapY(GL_CLAMP_TO_EDGE),
      m_wrapZ(GL_CLAMP_TO_EDGE),
      m_iGPUSize(0),
      m_iCPUSize(0)
{
    m_pTextures.resize(3);
}

GLVolume2DTex::~GLVolume2DTex() {
}

void GLVolume2DTex::Bind(UINT32 iUnit,
                         int depth,
                         int iStack) {
  if (depth < 0)
    m_pTextures[iStack][0]->Bind(iUnit);
  else
  if (static_cast<size_t>(depth) < m_pTextures[iStack].size())
    m_pTextures[iStack][depth]->Bind(iUnit);
  else
    m_pTextures[iStack][m_pTextures[iStack].size()-1]->Bind(iUnit);
}

void GLVolume2DTex::CreateGLResources() {
  m_pTextures[0].resize(m_iSizeX);
  for (size_t i = 0;i<m_pTextures[0].size();i++){
    m_pTextures[0][i] = new GLTexture2D(m_iSizeZ, m_iSizeY, m_internalformat,
                                        m_format, m_type, m_iSizePerElement,
                                        NULL, m_iMagFilter, m_iMinFilter,
                                        m_wrapZ, m_wrapY);
  }
  m_pTextures[1].resize(m_iSizeY);
  for (size_t i = 0;i<m_pTextures[1].size();i++){
    m_pTextures[1][i] = new GLTexture2D(m_iSizeX, m_iSizeZ, m_internalformat,
                                        m_format, m_type, m_iSizePerElement,
                                        NULL, m_iMagFilter, m_iMinFilter,
                                        m_wrapX, m_wrapZ);
  }
  m_pTextures[2].resize(m_iSizeZ);
  for (size_t i = 0;i<m_pTextures[2].size();i++){
    m_pTextures[2][i] = new GLTexture2D(m_iSizeX, m_iSizeY, m_internalformat,
                                        m_format, m_type, m_iSizePerElement,
                                        NULL, m_iMagFilter, m_iMinFilter,
                                        m_wrapX, m_wrapY);
  }
}

void GLVolume2DTex::FreeGLResources() {
  for (size_t iDir = 0;iDir<m_pTextures.size();iDir++){
    for (size_t i = 0;i<m_pTextures[iDir].size();i++){
      if (m_pTextures[iDir][i]) {
        m_pTextures[iDir][i]->Delete();
        delete m_pTextures[iDir][i];
      }
      m_pTextures[iDir][i] = NULL;
    }
    m_pTextures[iDir].resize(0);
  }
  m_iCPUSize = 0;
  m_iGPUSize = 0;
}

void GLVolume2DTex::SetData(const void *voxels) {
  // push data into the stacks
  // z is easy as this matches the data layout
  // x and y are more nasty and require a
  // random acces traversal througth the data, hence
  // the complicated indexing

  const char* charPtr = static_cast<const char*>(voxels);
  char* copyBuffer = new char[max(m_pTextures[0][0]->GetCPUSize(),
                                  m_pTextures[1][0]->GetCPUSize())];
  size_t sliceElemCount = m_iSizeY*m_iSizeX;

  for (size_t i = 0;i<m_pTextures[0].size();i++){
    size_t targetPos = 0;
    size_t sourcePos = 0;
    for (size_t y = 0;y<m_iSizeY;y++) {
      for (size_t z = 0;z<m_iSizeZ;z++) {
        // compute position in source array
        sourcePos = (i+y*m_iSizeX+z*sliceElemCount)*m_iSizePerElement;
        // copy one element into the target buffer
        memcpy(copyBuffer+targetPos,charPtr+sourcePos,m_iSizePerElement);
        targetPos += m_iSizePerElement;
      }
    }
    // copy into 2D texture slice
    m_pTextures[0][i]->SetData(copyBuffer);
  }

  for (size_t i = 0;i<m_pTextures[1].size();i++){
    size_t targetPos = 0;
    size_t sourcePos = 0;
    for (size_t z = 0;z<m_iSizeZ;z++) {
      for (size_t x = 0;x<m_iSizeX;x++) {
        // compute position in source array
        sourcePos = (x+i*m_iSizeX+z*sliceElemCount)*m_iSizePerElement;
        // copy one element into the target buffer
        memcpy(copyBuffer+targetPos,charPtr+sourcePos,m_iSizePerElement);
        targetPos += m_iSizePerElement;
      }
    }
    // copy into 2D texture slice
    m_pTextures[1][i]->SetData(copyBuffer);
  }

  delete[] copyBuffer;

  // z direction is easy
  size_t stepping = m_pTextures[2][0]->GetCPUSize();

  for (size_t i = 0;i<m_pTextures[2].size();i++){
    m_pTextures[2][i]->SetData(charPtr);
    charPtr += stepping;
  }
}

UINT64 GLVolume2DTex::GetCPUSize() {
  if (m_iCPUSize) return m_iCPUSize;

  UINT64 iSize = 0;
  for (size_t iDir = 0;iDir<m_pTextures.size();iDir++){
    for (size_t i = 0;i<m_pTextures[iDir].size();i++){
      iSize += m_pTextures[iDir][i]->GetCPUSize();
    }
  }
  return iSize;
}

UINT64 GLVolume2DTex::GetGPUSize() {
  if (m_iGPUSize) return m_iGPUSize;

  UINT64 iSize = 0;
  for (size_t iDir = 0;iDir<m_pTextures.size();iDir++){
    for (size_t i = 0;i<m_pTextures[iDir].size();i++){
      iSize += m_pTextures[iDir][i]->GetGPUSize();
    }
  }
  return iSize;
}<commit_msg>implemented a mirrored repeat-like texture assignment strategy at the boundaries (this turns the forward differences for the gradient computation int backward differences which is better than breaking them by implementing a clamp like behavior) lighting will still look odd (due to the flipping of the normal) but the gradient magnitude is correct<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2008 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

/**
  \file    GLVolume2DTex.cpp
  \author  Jens Krueger
           DFKI Saarbruecken & SCI Institute University of Utah
  \date    May 2010
*/

#include "GLVolume2DTex.h"
#include "GLTexture2D.h"
#include <cstring> // for memcpy

using namespace tuvok;
using namespace std;

GLVolume2DTex::GLVolume2DTex(UINT32 iSizeX, UINT32 iSizeY, UINT32 iSizeZ,
                             GLint internalformat, GLenum format, GLenum type,
                             UINT32 iSizePerElement,
                             const GLvoid *voxels,
                             GLint iMagFilter,
                             GLint iMinFilter,
                             GLint wrapX,
                             GLint wrapY,
                             GLint wrapZ) :
      m_iSizeX(iSizeX),
      m_iSizeY(iSizeY),
      m_iSizeZ(iSizeZ),
      m_internalformat(internalformat),
      m_format(format),
      m_type(type),
      m_iSizePerElement(iSizePerElement),
      m_iMagFilter(iMagFilter),
      m_iMinFilter(iMinFilter),
      m_wrapX(wrapX),
      m_wrapY(wrapY),
      m_wrapZ(wrapZ),
      m_iGPUSize(0),
      m_iCPUSize(0)
{
  m_pTextures.resize(3);
  CreateGLResources();
  SetData(voxels);
}

GLVolume2DTex::GLVolume2DTex() :
      m_iSizeX(0),
      m_iSizeY(0),
      m_iSizeZ(0),
      m_internalformat(0),
      m_format(0),
      m_type(0),
      m_iSizePerElement(0),
      m_iMagFilter(GL_NEAREST),
      m_iMinFilter(GL_NEAREST),
      m_wrapX(GL_CLAMP_TO_EDGE),
      m_wrapY(GL_CLAMP_TO_EDGE),
      m_wrapZ(GL_CLAMP_TO_EDGE),
      m_iGPUSize(0),
      m_iCPUSize(0)
{
    m_pTextures.resize(3);
}

GLVolume2DTex::~GLVolume2DTex() {
}

void GLVolume2DTex::Bind(UINT32 iUnit,
                         int depth,
                         int iStack) {
  if (depth < 0)
    m_pTextures[iStack][1]->Bind(iUnit); // resembles mirrored repeat
  else
  if (static_cast<size_t>(depth) < m_pTextures[iStack].size())
    m_pTextures[iStack][depth]->Bind(iUnit);
  else
    m_pTextures[iStack][m_pTextures[iStack].size()-2]->Bind(iUnit);
                                        // resembles mirrored repeat
}

void GLVolume2DTex::CreateGLResources() {
  m_pTextures[0].resize(m_iSizeX);
  for (size_t i = 0;i<m_pTextures[0].size();i++){
    m_pTextures[0][i] = new GLTexture2D(m_iSizeZ, m_iSizeY, m_internalformat,
                                        m_format, m_type, m_iSizePerElement,
                                        NULL, m_iMagFilter, m_iMinFilter,
                                        m_wrapZ, m_wrapY);
  }
  m_pTextures[1].resize(m_iSizeY);
  for (size_t i = 0;i<m_pTextures[1].size();i++){
    m_pTextures[1][i] = new GLTexture2D(m_iSizeX, m_iSizeZ, m_internalformat,
                                        m_format, m_type, m_iSizePerElement,
                                        NULL, m_iMagFilter, m_iMinFilter,
                                        m_wrapX, m_wrapZ);
  }
  m_pTextures[2].resize(m_iSizeZ);
  for (size_t i = 0;i<m_pTextures[2].size();i++){
    m_pTextures[2][i] = new GLTexture2D(m_iSizeX, m_iSizeY, m_internalformat,
                                        m_format, m_type, m_iSizePerElement,
                                        NULL, m_iMagFilter, m_iMinFilter,
                                        m_wrapX, m_wrapY);
  }
}

void GLVolume2DTex::FreeGLResources() {
  for (size_t iDir = 0;iDir<m_pTextures.size();iDir++){
    for (size_t i = 0;i<m_pTextures[iDir].size();i++){
      if (m_pTextures[iDir][i]) {
        m_pTextures[iDir][i]->Delete();
        delete m_pTextures[iDir][i];
      }
      m_pTextures[iDir][i] = NULL;
    }
    m_pTextures[iDir].resize(0);
  }
  m_iCPUSize = 0;
  m_iGPUSize = 0;
}

void GLVolume2DTex::SetData(const void *voxels) {
  // push data into the stacks
  // z is easy as this matches the data layout
  // x and y are more nasty and require a
  // random acces traversal througth the data, hence
  // the complicated indexing

  const char* charPtr = static_cast<const char*>(voxels);
  char* copyBuffer = new char[max(m_pTextures[0][0]->GetCPUSize(),
                                  m_pTextures[1][0]->GetCPUSize())];
  size_t sliceElemCount = m_iSizeY*m_iSizeX;

  for (size_t i = 0;i<m_pTextures[0].size();i++){
    size_t targetPos = 0;
    size_t sourcePos = 0;
    for (size_t y = 0;y<m_iSizeY;y++) {
      for (size_t z = 0;z<m_iSizeZ;z++) {
        // compute position in source array
        sourcePos = (i+y*m_iSizeX+z*sliceElemCount)*m_iSizePerElement;
        // copy one element into the target buffer
        memcpy(copyBuffer+targetPos,charPtr+sourcePos,m_iSizePerElement);
        targetPos += m_iSizePerElement;
      }
    }
    // copy into 2D texture slice
    m_pTextures[0][i]->SetData(copyBuffer);
  }

  for (size_t i = 0;i<m_pTextures[1].size();i++){
    size_t targetPos = 0;
    size_t sourcePos = 0;
    for (size_t z = 0;z<m_iSizeZ;z++) {
      for (size_t x = 0;x<m_iSizeX;x++) {
        // compute position in source array
        sourcePos = (x+i*m_iSizeX+z*sliceElemCount)*m_iSizePerElement;
        // copy one element into the target buffer
        memcpy(copyBuffer+targetPos,charPtr+sourcePos,m_iSizePerElement);
        targetPos += m_iSizePerElement;
      }
    }
    // copy into 2D texture slice
    m_pTextures[1][i]->SetData(copyBuffer);
  }

  delete[] copyBuffer;

  // z direction is easy
  size_t stepping = m_pTextures[2][0]->GetCPUSize();

  for (size_t i = 0;i<m_pTextures[2].size();i++){
    m_pTextures[2][i]->SetData(charPtr);
    charPtr += stepping;
  }
}

UINT64 GLVolume2DTex::GetCPUSize() {
  if (m_iCPUSize) return m_iCPUSize;

  UINT64 iSize = 0;
  for (size_t iDir = 0;iDir<m_pTextures.size();iDir++){
    for (size_t i = 0;i<m_pTextures[iDir].size();i++){
      iSize += m_pTextures[iDir][i]->GetCPUSize();
    }
  }
  return iSize;
}

UINT64 GLVolume2DTex::GetGPUSize() {
  if (m_iGPUSize) return m_iGPUSize;

  UINT64 iSize = 0;
  for (size_t iDir = 0;iDir<m_pTextures.size();iDir++){
    for (size_t i = 0;i<m_pTextures[iDir].size();i++){
      iSize += m_pTextures[iDir][i]->GetGPUSize();
    }
  }
  return iSize;
}<|endoftext|>