<commit_before>#include <QSignalSpy>
#include "shoppinglist-t.h"
#include "shoppinglist.h"
#include <QTableView>

void ShoppingListTest::init()
{
	shoppingList = new ShoppingList;
}

void ShoppingListTest::cleanup()
{
	delete shoppingList;
}

void ShoppingListTest::testNewItem()
{
	QString item_1 = "test_item";
	QString item_2 = "test_item_2";

	double price = 20.0;
	int amount = 10;

	//basic test of add
	QCOMPARE(shoppingList->rowCount(), 0);
	shoppingList->newItem(item_1, price, amount);
	QCOMPARE(shoppingList->data(shoppingList->index(0, 0)).toString(), item_1);

	//add another item, verify it is added in a new row
	QCOMPARE(shoppingList->rowCount(), 1);
	shoppingList->newItem(item_2, price, amount);
	QCOMPARE(shoppingList->rowCount(), 2);
	QCOMPARE(shoppingList->data(shoppingList->index(1, 0)).toString(), item_1);

	//verify the other elements
	QCOMPARE(shoppingList->data(shoppingList->index(1, 1)).toDouble(), price);
	QCOMPARE(shoppingList->data(shoppingList->index(1, 2)).toInt(), amount);

	//add item with same name, verify it overwrites the former item
	double price_2 = 30.0;
	int amount_2 = 30;
	shoppingList->newItem(item_2, price_2, amount_2);
	QCOMPARE(shoppingList->rowCount(), 2);
	QCOMPARE(shoppingList->data(shoppingList->index(1, 1)).toDouble(), price_2);
	QCOMPARE(shoppingList->data(shoppingList->index(1, 2)).toInt(), amount_2);
}

void ShoppingListTest::testSetItemAmount()
{
	int amount = 20;
	shoppingList->newItem("test_item_1", 20.0, amount);
	shoppingList->newItem("test_item_2", 20.0, amount);
	shoppingList->newItem("test_item_3", 20.0, amount);

	QCOMPARE(shoppingList->data(shoppingList->index(2, 2)).toInt(), amount);

	//check that the amount is changed when requested
	shoppingList->setItemAmount("test_item_3", amount*2);
	QCOMPARE(shoppingList->data(shoppingList->index(2, 2)).toInt(), amount*2);
}

void ShoppingListTest::testDeleteItem()
{
	int amount = 20;
	shoppingList->newItem("test_item_1", 20.0, amount);
	shoppingList->newItem("test_item_2", 20.0, amount);
	shoppingList->newItem("test_item_3", 20.0, amount);

	QCOMPARE(shoppingList->rowCount(), 3);

	//check that correct row is deleted when using the item name
	shoppingList->deleteItem("test_item_2");
	QCOMPARE(shoppingList->rowCount(), 2);
	QCOMPARE(shoppingList->data(shoppingList->index(0, 0)).toString(), QString("test_item_1"));
	QCOMPARE(shoppingList->data(shoppingList->index(1, 0)).toString(), QString("test_item_3"));

	//check that the correct row is deleted when using the row number
	shoppingList->deleteItem(shoppingList->index(0, 0));
	QCOMPARE(shoppingList->data(shoppingList->index(0, 0)).toString(), QString("test_item_3"));
}

void ShoppingListTest::testWipeList()
{
	int amount = 20;
	shoppingList->newItem("test_item_1", 20.0, amount);
	shoppingList->newItem("test_item_2", 20.0, amount);
	shoppingList->newItem("test_item_3", 20.0, amount);
	QCOMPARE(shoppingList->rowCount(), 3);

	//verify that list is wiped
	shoppingList->wipeList();
	QCOMPARE(shoppingList->rowCount(), 0);
	QCOMPARE(shoppingList->data(shoppingList->index(0, 0)), QVariant(QVariant::Invalid));
	shoppingList->wipeList();
	QCOMPARE(shoppingList->rowCount(), 0);
}

void ShoppingListTest::testDeleteLastItem()
{
	int amount = 20;
	shoppingList->newItem("test_item_1", 20.0, amount);
	shoppingList->newItem("test_item_2", 20.0, amount);
	shoppingList->newItem("test_item_3", 20.0, amount);
	QCOMPARE(shoppingList->rowCount(), 3);

	//verify that last item was deleted
	shoppingList->deleteLastAddedItem();
	QCOMPARE(shoppingList->rowCount(), 2);
	QCOMPARE(shoppingList->data(shoppingList->index(0, 0)).toString(), QString("test_item_1"));
	QCOMPARE(shoppingList->data(shoppingList->index(1, 0)).toString(), QString("test_item_2"));
}

void ShoppingListTest::testGetTotalAmount()
{
	QCOMPARE(shoppingList->getTotalAmount(), 0.0);
	int amount = 20;
	double price = 20;
	shoppingList->newItem("test_item_1", price, amount);
	QCOMPARE(shoppingList->getTotalAmount(), price*amount*1.0);
	shoppingList->newItem("test_item_2", price, amount);
	QCOMPARE(shoppingList->getTotalAmount(), 2*price*amount*1.0);
	shoppingList->newItem("test_item_3", price, amount);
	QCOMPARE(shoppingList->getTotalAmount(), 3*price*amount*1.0);
}

QTEST_MAIN(ShoppingListTest)
<commit_msg>Add note about data population<commit_after>#include <QSignalSpy>
#include "shoppinglist-t.h"
#include "shoppinglist.h"
#include <QTableView>

void ShoppingListTest::init()
{
	shoppingList = new ShoppingList;

	//TODO: Since all tests mostly use the same data, populate the shoppingList here.
}

void ShoppingListTest::cleanup()
{
	delete shoppingList;
}

void ShoppingListTest::testNewItem()
{
	QString item_1 = "test_item";
	QString item_2 = "test_item_2";

	double price = 20.0;
	int amount = 10;

	//basic test of add
	QCOMPARE(shoppingList->rowCount(), 0);
	shoppingList->newItem(item_1, price, amount);
	QCOMPARE(shoppingList->data(shoppingList->index(0, 0)).toString(), item_1);

	//add another item, verify it is added in a new row
	QCOMPARE(shoppingList->rowCount(), 1);
	shoppingList->newItem(item_2, price, amount);
	QCOMPARE(shoppingList->rowCount(), 2);
	QCOMPARE(shoppingList->data(shoppingList->index(1, 0)).toString(), item_1);

	//verify the other elements
	QCOMPARE(shoppingList->data(shoppingList->index(1, 1)).toDouble(), price);
	QCOMPARE(shoppingList->data(shoppingList->index(1, 2)).toInt(), amount);

	//add item with same name, verify it overwrites the former item
	double price_2 = 30.0;
	int amount_2 = 30;
	shoppingList->newItem(item_2, price_2, amount_2);
	QCOMPARE(shoppingList->rowCount(), 2);
	QCOMPARE(shoppingList->data(shoppingList->index(1, 1)).toDouble(), price_2);
	QCOMPARE(shoppingList->data(shoppingList->index(1, 2)).toInt(), amount_2);
}

void ShoppingListTest::testSetItemAmount()
{
	int amount = 20;
	shoppingList->newItem("test_item_1", 20.0, amount);
	shoppingList->newItem("test_item_2", 20.0, amount);
	shoppingList->newItem("test_item_3", 20.0, amount);

	QCOMPARE(shoppingList->data(shoppingList->index(2, 2)).toInt(), amount);

	//check that the amount is changed when requested
	shoppingList->setItemAmount("test_item_3", amount*2);
	QCOMPARE(shoppingList->data(shoppingList->index(2, 2)).toInt(), amount*2);
}

void ShoppingListTest::testDeleteItem()
{
	int amount = 20;
	shoppingList->newItem("test_item_1", 20.0, amount);
	shoppingList->newItem("test_item_2", 20.0, amount);
	shoppingList->newItem("test_item_3", 20.0, amount);

	QCOMPARE(shoppingList->rowCount(), 3);

	//check that correct row is deleted when using the item name
	shoppingList->deleteItem("test_item_2");
	QCOMPARE(shoppingList->rowCount(), 2);
	QCOMPARE(shoppingList->data(shoppingList->index(0, 0)).toString(), QString("test_item_1"));
	QCOMPARE(shoppingList->data(shoppingList->index(1, 0)).toString(), QString("test_item_3"));

	//check that the correct row is deleted when using the row number
	shoppingList->deleteItem(shoppingList->index(0, 0));
	QCOMPARE(shoppingList->data(shoppingList->index(0, 0)).toString(), QString("test_item_3"));
}

void ShoppingListTest::testWipeList()
{
	int amount = 20;
	shoppingList->newItem("test_item_1", 20.0, amount);
	shoppingList->newItem("test_item_2", 20.0, amount);
	shoppingList->newItem("test_item_3", 20.0, amount);
	QCOMPARE(shoppingList->rowCount(), 3);

	//verify that list is wiped
	shoppingList->wipeList();
	QCOMPARE(shoppingList->rowCount(), 0);
	QCOMPARE(shoppingList->data(shoppingList->index(0, 0)), QVariant(QVariant::Invalid));
	shoppingList->wipeList();
	QCOMPARE(shoppingList->rowCount(), 0);
}

void ShoppingListTest::testDeleteLastItem()
{
	int amount = 20;
	shoppingList->newItem("test_item_1", 20.0, amount);
	shoppingList->newItem("test_item_2", 20.0, amount);
	shoppingList->newItem("test_item_3", 20.0, amount);
	QCOMPARE(shoppingList->rowCount(), 3);

	//verify that last item was deleted
	shoppingList->deleteLastAddedItem();
	QCOMPARE(shoppingList->rowCount(), 2);
	QCOMPARE(shoppingList->data(shoppingList->index(0, 0)).toString(), QString("test_item_1"));
	QCOMPARE(shoppingList->data(shoppingList->index(1, 0)).toString(), QString("test_item_2"));
}

void ShoppingListTest::testGetTotalAmount()
{
	QCOMPARE(shoppingList->getTotalAmount(), 0.0);
	int amount = 20;
	double price = 20;
	shoppingList->newItem("test_item_1", price, amount);
	QCOMPARE(shoppingList->getTotalAmount(), price*amount*1.0);
	shoppingList->newItem("test_item_2", price, amount);
	QCOMPARE(shoppingList->getTotalAmount(), 2*price*amount*1.0);
	shoppingList->newItem("test_item_3", price, amount);
	QCOMPARE(shoppingList->getTotalAmount(), 3*price*amount*1.0);
}

QTEST_MAIN(ShoppingListTest)
<|endoftext|>


<commit_before>
#include <gtest/gtest.h>
#include <string>
#include <vector>

#include "sqlite_db.h"

static std::string const spath = "testdb.sqlite";

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class SqliteDbTests : public ::testing::Test {
 public:
  virtual void SetUp() {
    path = "somedb.sqlite";
    v1 = "stuff";
    v2 = "thing";
    db = new cyclus::SqliteDb(path);
    db->open();
    db->Execute("create table t1 (data1 TEXT, data2 TEXT);");
    db->Execute(
        "insert into t1 (data1, data2) values ('" + v1 + "', '" + v2 + "');");
  }

  virtual void TearDown() {
    db->close();
    delete db;
    remove(path.c_str());
  }

  cyclus::SqliteDb* db;
  std::string path, v1, v2;
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(SqliteDbTests, OpenExistingAndRetrieve) {
  using cyclus::StrList;
  std::vector<StrList> result;

  ASSERT_NO_THROW(result = db->Query("select * from t1"));
  ASSERT_EQ(result.size(), 1);
  ASSERT_EQ(result.front().size(), 2);
  EXPECT_EQ(result.front().front(), v1);
  EXPECT_EQ(result.front().back(), v2);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(SqliteDbTests, Overwrite) {
  using cyclus::SqliteDb;
  using cyclus::StrList;
  std::vector<StrList> result;

  db->close();
  db->Overwrite();

  ASSERT_NO_THROW(db->open());

  ASSERT_NO_THROW(result = db->Query("select * from sqlite_master"));
  EXPECT_EQ(result.size(), 0);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST(SqliteDbTest, CreateAndInsert) {
  using cyclus::SqliteDb;
  using cyclus::StrList;
  remove(spath.c_str());
  std::vector<StrList> result;
  SqliteDb db(spath);

  ASSERT_NO_THROW(db.open());

  ASSERT_NO_THROW(db.Execute("create table t1 (data1 TEXT, data2 TEXT);"));
  ASSERT_NO_THROW(db.Execute(
      "insert into t1 (data1, data2) values ('hello', 'goodbye');"));
  ASSERT_NO_THROW(result = db.Query("select * from t1"));
  ASSERT_EQ(result.size(), 1);
  ASSERT_EQ(result.front().size(), 2);
  EXPECT_EQ(result.front().front(), "hello");
  EXPECT_EQ(result.front().back(), "goodbye");

  ASSERT_NO_THROW(db.close());
}

<commit_msg>small filename change<commit_after>
#include <gtest/gtest.h>
#include <string>
#include <vector>

#include "sqlite_db.h"

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class SqliteDbTests : public ::testing::Test {
 public:
  virtual void SetUp() {
    path = "testdb.sqlite";
    v1 = "stuff";
    v2 = "thing";
    db = new cyclus::SqliteDb(path);
    db->open();
    db->Execute("create table t1 (data1 TEXT, data2 TEXT);");
    db->Execute(
        "insert into t1 (data1, data2) values ('" + v1 + "', '" + v2 + "');");
  }

  virtual void TearDown() {
    db->close();
    delete db;
    remove(path.c_str());
  }

  cyclus::SqliteDb* db;
  std::string path, v1, v2;
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(SqliteDbTests, OpenExistingAndRetrieve) {
  using cyclus::StrList;
  std::vector<StrList> result;

  ASSERT_NO_THROW(result = db->Query("select * from t1"));
  ASSERT_EQ(result.size(), 1);
  ASSERT_EQ(result.front().size(), 2);
  EXPECT_EQ(result.front().front(), v1);
  EXPECT_EQ(result.front().back(), v2);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(SqliteDbTests, Overwrite) {
  using cyclus::SqliteDb;
  using cyclus::StrList;
  std::vector<StrList> result;

  db->close();
  db->Overwrite();

  ASSERT_NO_THROW(db->open());

  ASSERT_NO_THROW(result = db->Query("select * from sqlite_master"));
  EXPECT_EQ(result.size(), 0);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST(SqliteDbTest, CreateAndInsert) {
  using cyclus::SqliteDb;
  using cyclus::StrList;
  std::vector<StrList> result;

  std::string path = "somedb.sqlite";
  SqliteDb db(path);

  ASSERT_NO_THROW(db.open());

  ASSERT_NO_THROW(db.Execute("create table t1 (data1 TEXT, data2 TEXT);"));
  ASSERT_NO_THROW(db.Execute(
      "insert into t1 (data1, data2) values ('hello', 'goodbye');"));
  ASSERT_NO_THROW(result = db.Query("select * from t1"));
  ASSERT_EQ(result.size(), 1);
  ASSERT_EQ(result.front().size(), 2);
  EXPECT_EQ(result.front().front(), "hello");
  EXPECT_EQ(result.front().back(), "goodbye");

  ASSERT_NO_THROW(db.close());
  remove(path.c_str());
}

<|endoftext|>


<commit_before>//
// Created by 理 傅 on 16/7/9.
//

#include "sess.h"
#include <sys/socket.h>
#include <sys/fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>

UDPSession *
UDPSession::Dial(const char *ip, uint16_t port) {
    int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        return nullptr;
    }

    struct sockaddr_in saddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(port);
    inet_aton(ip, &(saddr.sin_addr));
    if (connect(sockfd, (struct sockaddr *) &saddr, sizeof(struct sockaddr)) < 0) {
        close(sockfd);
        return nullptr;
    }

    int flags = fcntl(sockfd, F_GETFL, 0);
    if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
        close(sockfd);
        return nullptr;
    }

    void *buf = malloc(UDPSession::mtuLimit);
    if (buf == nullptr) {
        close(sockfd);
        return nullptr;
    }

    UDPSession *sess = new UDPSession;
    auto kcp = ikcp_create(IUINT32(rand()), sess);
    sess->m_sockfd = sockfd;
    sess->m_kcp = kcp;
    sess->m_kcp->output = sess->out_wrapper;
    sess->m_buf = buf;
    sess->m_bufsiz = UDPSession::mtuLimit;
    if (kcp == nullptr) {
        sess->Close();
        return nullptr;
    }
    return sess;
}

UDPSession *
UDPSession::DialIPv6(const char *ip, uint16_t port) {
    int sockfd = socket(PF_INET6, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        return nullptr;
    }
    struct sockaddr_in6 saddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin6_family = AF_INET6;
    saddr.sin6_port = htons(port);
    inet_pton(AF_INET6, ip, &(saddr.sin6_addr));

    if (connect(sockfd, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in6)) < 0) {
        close(sockfd);
        return nullptr;
    }

    int flags = fcntl(sockfd, F_GETFL, 0);
    if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
        close(sockfd);
        return nullptr;
    }

    void *buf = malloc(UDPSession::mtuLimit);
    if (buf == nullptr) {
        close(sockfd);
        return nullptr;
    }

    UDPSession *sess = new UDPSession;
    auto kcp = ikcp_create(IUINT32(rand()), sess);
    sess->m_sockfd = sockfd;
    sess->m_kcp = kcp;
    sess->m_kcp->output = sess->out_wrapper;
    sess->m_buf = buf;
    sess->m_bufsiz = UDPSession::mtuLimit;
    if (kcp == nullptr) {
        sess->Close();
        return nullptr;
    }
    return sess;
}

void
UDPSession::Update(uint32_t current) {
    while (1) {
        ssize_t n = recv(m_sockfd, m_buf, m_bufsiz, 0);
        if (n > 0) {
            ikcp_input(m_kcp, static_cast<const char *>(m_buf), n);
        } else {
            break;
        }
    }
    ikcp_update(m_kcp, current);
}

void
UDPSession::Close() {
    if (m_sockfd != 0) { close(m_sockfd); }
    if (m_buf != 0) { free(m_buf); }
    if (m_kcp != 0) { ikcp_release(m_kcp); }
    delete this;
}

int
UDPSession::out_wrapper(const char *buf, int len, struct IKCPCB *, void *user) {
    assert(user != nullptr);
    UDPSession *sess = static_cast<UDPSession *>(user);
    return (int)sess->output(buf, static_cast<size_t>(len));
}

ssize_t
UDPSession::output(const void *buffer, size_t length) {
    ssize_t n = send(m_sockfd, buffer, length, 0);
    return n;
}<commit_msg>update<commit_after>//
// Created by 理 傅 on 16/7/9.
//

#include "sess.h"
#include <sys/socket.h>
#include <sys/fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>

UDPSession *
UDPSession::Dial(const char *ip, uint16_t port) {
    int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        return nullptr;
    }

    struct sockaddr_in saddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(port);
    inet_aton(ip, &(saddr.sin_addr));
    if (connect(sockfd, (struct sockaddr *) &saddr, sizeof(struct sockaddr)) < 0) {
        close(sockfd);
        return nullptr;
    }

    int flags = fcntl(sockfd, F_GETFL, 0);
    if (flags < 0) {
        close(sockfd);
        return nullptr;
    }

    if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
        close(sockfd);
        return nullptr;
    }

    void *buf = malloc(UDPSession::mtuLimit);
    if (buf == nullptr) {
        close(sockfd);
        return nullptr;
    }

    UDPSession *sess = new UDPSession;
    auto kcp = ikcp_create(IUINT32(rand()), sess);
    sess->m_sockfd = sockfd;
    sess->m_kcp = kcp;
    sess->m_kcp->output = sess->out_wrapper;
    sess->m_buf = buf;
    sess->m_bufsiz = UDPSession::mtuLimit;
    if (kcp == nullptr) {
        sess->Close();
        return nullptr;
    }
    return sess;
}

UDPSession *
UDPSession::DialIPv6(const char *ip, uint16_t port) {
    int sockfd = socket(PF_INET6, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        return nullptr;
    }
    struct sockaddr_in6 saddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin6_family = AF_INET6;
    saddr.sin6_port = htons(port);
    inet_pton(AF_INET6, ip, &(saddr.sin6_addr));

    if (connect(sockfd, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in6)) < 0) {
        close(sockfd);
        return nullptr;
    }

    int flags = fcntl(sockfd, F_GETFL, 0);
    if (flags < 0) {
        close(sockfd);
        return nullptr;
    }

    if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
        close(sockfd);
        return nullptr;
    }

    void *buf = malloc(UDPSession::mtuLimit);
    if (buf == nullptr) {
        close(sockfd);
        return nullptr;
    }

    UDPSession *sess = new UDPSession;
    auto kcp = ikcp_create(IUINT32(rand()), sess);
    sess->m_sockfd = sockfd;
    sess->m_kcp = kcp;
    sess->m_kcp->output = sess->out_wrapper;
    sess->m_buf = buf;
    sess->m_bufsiz = UDPSession::mtuLimit;
    if (kcp == nullptr) {
        sess->Close();
        return nullptr;
    }
    return sess;
}

void
UDPSession::Update(uint32_t current) {
    while (1) {
        ssize_t n = recv(m_sockfd, m_buf, m_bufsiz, 0);
        if (n > 0) {
            ikcp_input(m_kcp, static_cast<const char *>(m_buf), n);
        } else {
            break;
        }
    }
    ikcp_update(m_kcp, current);
}

void
UDPSession::Close() {
    if (m_sockfd != 0) { close(m_sockfd); }
    if (m_buf != 0) { free(m_buf); }
    if (m_kcp != 0) { ikcp_release(m_kcp); }
    delete this;
}

int
UDPSession::out_wrapper(const char *buf, int len, struct IKCPCB *, void *user) {
    assert(user != nullptr);
    UDPSession *sess = static_cast<UDPSession *>(user);
    return (int)sess->output(buf, static_cast<size_t>(len));
}

ssize_t
UDPSession::output(const void *buffer, size_t length) {
    ssize_t n = send(m_sockfd, buffer, length, 0);
    return n;
}<|endoftext|>


<commit_before>#include "sim_obj.h"
#include <vector>
#include <cmath>
#include <iostream>
using namespace std;

void sim_obj::resizeMatrix(vector<vector<double>>& p_Matrix, int newSize) {
  p_Matrix.clear();
  p_Matrix.resize(newSize, vector<double>(newSize, 0));
}

double sim_obj::calcCompDistance(int bodyID_A, int bodyID_B, int xy) {
  double posA = bodyStore[bodyID_A].getPosition(xy);
  double posB = bodyStore[bodyID_B].getPosition(xy);
  // Return component distance
  return posA - posB;
}

double sim_obj::calcVectDistance(double distX, double distY) {
  return sqrt(pow(abs(distX),2) + pow(abs(distY), 2));
}

double sim_obj::calcForceBodyPair(int bodyID_A, int bodyID_B, int xy) {
  double distX, distY, distV;
  // Component Distance
  distX = calcCompDistance(bodyID_A, bodyID_B, 0);
  distY = calcCompDistance(bodyID_A, bodyID_B, 1);
  // Vector Distance
  distV = calcVectDistance(distX, distY);

  // GMm/(r^3)
  double forceResult;
  forceResult = gravitationalConstant * bodyStore[bodyID_A].getMass() * bodyStore[bodyID_B].getMass();
  forceResult /= pow(distV, 3);

  if (xy)
    forceResult *= distY;
  else
    forceResult *= distX;
  return -forceResult;
}

int sim_obj::calcForceMatrix() {
  resizeMatrix(forceMatrix, bodyStore.size());
  prevBodyCount = bodyStore.size();

  // Loop Half Matrix
  for (int xAccess = 0; xAccess < bodyStore.size(); xAccess++) {
    for (int yAccess = xAccess + 1; yAccess < bodyStore.size(); yAccess++) {
      // Skip if checking same body
      if (xAccess != yAccess) {
        forceMatrix[xAccess][yAccess] = calcForceBodyPair(xAccess, yAccess, 0);
        forceMatrix[yAccess][xAccess] = calcForceBodyPair(xAccess, yAccess, 1);
      }
    }
  }

  // Return Success
  return 0;
}
// Applies to All Bodies, sets in body vector.
int sim_obj::calcForceSumAB() {
  for (int bodyIDC = 0; bodyIDC < bodyStore.size(); bodyIDC++) {
    bodyStore[bodyIDC].resetForce();
  }
  for (int xAccess = 0; xAccess < bodyStore.size(); xAccess++) {
    for (int yAccess = 0; yAccess < bodyStore.size(); yAccess++) {
      // Ignore Middle Diagonal
      if (yAccess != xAccess) {
        // If yAccess is smaller than xAccess, flip coordinates to stay within half matrix.
        if (yAccess < xAccess) {
          // Add Component force to get total component forces for x and y.
          bodyStore[xAccess].addForce(-forceMatrix[yAccess][xAccess], 0);
          bodyStore[yAccess].addForce( forceMatrix[xAccess][yAccess], 1);
        } else {
          bodyStore[xAccess].addForce( forceMatrix[xAccess][yAccess], 0);
          bodyStore[yAccess].addForce(-forceMatrix[yAccess][xAccess], 1);
        }
      }
    }
  }
  return 0;
}

int sim_obj::calcAcceleraitonAB() {
  // Update Forces before Acceleration Update
  for (int bodyIDC = 0; bodyIDC < bodyStore.size(); bodyIDC++) {
    bodyStore[bodyIDC].calcAcceleration();
    //cout << bodyIDC << " : " << bodyStore[bodyIDC].getAcceleration(0) << ", " << bodyStore[bodyIDC].getAcceleration(1) << endl;
  }
  return 0;
}

int sim_obj::calcHalfVelocityAB() {
  for (int bodyIDC = 0; bodyIDC < bodyStore.size(); bodyIDC++) {
    bodyStore[bodyIDC].calcHalfVelocity();
    //cout << bodyIDC << " : " << bodyStore[bodyIDC].getVelocity(0) << ", " << bodyStore[bodyIDC].getVelocity(1) << endl;
  }
  return 0;
}

int sim_obj::calcPositionAB() {
  for (int bodyIDC = 0; bodyIDC < bodyStore.size(); bodyIDC++) {
    bodyStore[bodyIDC].calcPosition();
  }
  return 0;
}

sim_obj::sim_obj() {
}

sim_obj::~sim_obj() {
}

int sim_obj::itteration() {
  if (scenarioChanged) {
    // Calculate Initial Forces and Accelerations
    calcForceMatrix();
    calcForceSumAB();
    calcAcceleraitonAB();
    scenarioChanged = false;
  }

  // Move Half for Half Time
  calcHalfVelocityAB();
  calcPositionAB();

  // Update Forces and Accelerations
  calcForceMatrix();
  calcForceSumAB();
  calcAcceleraitonAB();

  // Calculate New Velocity
  calcHalfVelocityAB();

  return 0;
}

void sim_obj::outputTest() {
  cout << bodyStore[0].getPosition(0) << " " << bodyStore[0].getPosition(1) << " " << bodyStore[1].getPosition(0) << " " << bodyStore[1].getPosition(1) << " " << bodyStore[2].getPosition(0) << " " << bodyStore[2].getPosition(1) << endl;
}
<commit_msg>Fixed warnings about unsigned comparisons.<commit_after>#include "sim_obj.h"
#include <vector>
#include <cmath>
#include <iostream>
using namespace std;

void sim_obj::resizeMatrix(vector<vector<double>>& p_Matrix, int newSize) {
  p_Matrix.clear();
  p_Matrix.resize(newSize, vector<double>(newSize, 0));
}

double sim_obj::calcCompDistance(int bodyID_A, int bodyID_B, int xy) {
  double posA = bodyStore[bodyID_A].getPosition(xy);
  double posB = bodyStore[bodyID_B].getPosition(xy);
  // Return component distance
  return posA - posB;
}

double sim_obj::calcVectDistance(double distX, double distY) {
  return sqrt(pow(abs(distX),2) + pow(abs(distY), 2));
}

double sim_obj::calcForceBodyPair(int bodyID_A, int bodyID_B, int xy) {
  double distX, distY, distV;
  // Component Distance
  distX = calcCompDistance(bodyID_A, bodyID_B, 0);
  distY = calcCompDistance(bodyID_A, bodyID_B, 1);
  // Vector Distance
  distV = calcVectDistance(distX, distY);

  // GMm/(r^3)
  double forceResult;
  forceResult = gravitationalConstant * bodyStore[bodyID_A].getMass() * bodyStore[bodyID_B].getMass();
  forceResult /= pow(distV, 3);

  if (xy)
    forceResult *= distY;
  else
    forceResult *= distX;
  return -forceResult;
}

int sim_obj::calcForceMatrix() {
  resizeMatrix(forceMatrix, bodyStore.size());
  prevBodyCount = bodyStore.size();

  // Loop Half Matrix
  for (unsigned int xAccess = 0; xAccess < bodyStore.size(); xAccess++) {
    for (unsigned int yAccess = xAccess + 1; yAccess < bodyStore.size(); yAccess++) {
      // Skip if checking same body
      if (xAccess != yAccess) {
        forceMatrix[xAccess][yAccess] = calcForceBodyPair(xAccess, yAccess, 0);
        forceMatrix[yAccess][xAccess] = calcForceBodyPair(xAccess, yAccess, 1);
      }
    }
  }

  // Return Success
  return 0;
}
// Applies to All Bodies, sets in body vector.
int sim_obj::calcForceSumAB() {
  for (unsigned int bodyIDC = 0; bodyIDC < bodyStore.size(); bodyIDC++) {
    bodyStore[bodyIDC].resetForce();
  }
  for (unsigned int xAccess = 0; xAccess < bodyStore.size(); xAccess++) {
    for (unsigned int yAccess = 0; yAccess < bodyStore.size(); yAccess++) {
      // Ignore Middle Diagonal
      if (yAccess != xAccess) {
        // If yAccess is smaller than xAccess, flip coordinates to stay within half matrix.
        if (yAccess < xAccess) {
          // Add Component force to get total component forces for x and y.
          bodyStore[xAccess].addForce(-forceMatrix[yAccess][xAccess], 0);
          bodyStore[yAccess].addForce( forceMatrix[xAccess][yAccess], 1);
        } else {
          bodyStore[xAccess].addForce( forceMatrix[xAccess][yAccess], 0);
          bodyStore[yAccess].addForce(-forceMatrix[yAccess][xAccess], 1);
        }
      }
    }
  }
  return 0;
}

int sim_obj::calcAcceleraitonAB() {
  // Update Forces before Acceleration Update
  for (unsigned int bodyIDC = 0; bodyIDC < bodyStore.size(); bodyIDC++) {
    bodyStore[bodyIDC].calcAcceleration();
    //cout << bodyIDC << " : " << bodyStore[bodyIDC].getAcceleration(0) << ", " << bodyStore[bodyIDC].getAcceleration(1) << endl;
  }
  return 0;
}

int sim_obj::calcHalfVelocityAB() {
  for (unsigned int bodyIDC = 0; bodyIDC < bodyStore.size(); bodyIDC++) {
    bodyStore[bodyIDC].calcHalfVelocity();
    //cout << bodyIDC << " : " << bodyStore[bodyIDC].getVelocity(0) << ", " << bodyStore[bodyIDC].getVelocity(1) << endl;
  }
  return 0;
}

int sim_obj::calcPositionAB() {
  for (unsigned int bodyIDC = 0; bodyIDC < bodyStore.size(); bodyIDC++) {
    bodyStore[bodyIDC].calcPosition();
  }
  return 0;
}

sim_obj::sim_obj() {
}

sim_obj::~sim_obj() {
}

int sim_obj::itteration() {
  if (scenarioChanged) {
    // Calculate Initial Forces and Accelerations
    calcForceMatrix();
    calcForceSumAB();
    calcAcceleraitonAB();
    scenarioChanged = false;
  }

  // Move Half for Half Time
  calcHalfVelocityAB();
  calcPositionAB();

  // Update Forces and Accelerations
  calcForceMatrix();
  calcForceSumAB();
  calcAcceleraitonAB();

  // Calculate New Velocity
  calcHalfVelocityAB();

  return 0;
}

void sim_obj::outputTest() {
  cout << bodyStore[0].getPosition(0) << " " << bodyStore[0].getPosition(1) << " " << bodyStore[1].getPosition(0) << " " << bodyStore[1].getPosition(1) << " " << bodyStore[2].getPosition(0) << " " << bodyStore[2].getPosition(1) << endl;
}
<|endoftext|>


<commit_before><commit_msg>Add new card ID<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include "errno.h"
#include <string>
#include <vector>
#include <list>
#include "boost/tokenizer.hpp"

using namespace std;

int main (int argc, char const *argv[])
{
    char host[128];
    gethostname(host, sizeof(host));
    char * login = getlogin();

	string input;

    while(true)
	{
        //Terminal prompt display
        cout << login << "@" << host << " $ ";
        cout.flush();

        //Grab user input for bash prompt
        getline(cin,input);

        //Setting up a boost tokenizer.
        typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
        boost::char_separator<char> sep(" ", ";"); //' ' (space) as delmieter
        tokenizer tok(input, sep);

        //ls is a temp list for storing the tokenized value
        list<string> ls;
        //vector for storing a command and its arguments
        vector<char*> args;
        //vector for storing all of the commands that have been chained together
        vector<vector<char*> > commands;

        /*
        Check for # and immediatly end parsing since anything after it is a comment.
        Check for ; or || or && to know if a new command needs to be created.
        Put all of these new commands in the commands vector.
        */
        for(tokenizer::iterator it = tok.begin(); it != tok.end(); ++it) {
            if(*it == "#")
                break;
            if(*it == ";" || *it == "||" || *it == "&&") {
                args.push_back(0);
                commands.push_back(args);
                args.clear();
            }
            else {
                ls.push_back(*it);
                args.push_back(const_cast<char*>(ls.back().c_str()));
            }
        }
        args.push_back(0);
        commands.push_back(args);

        //Go through all of the commands
        for(int x = 0; x < commands.size(); x++) {

            //Get the current command
            vector<char*> com = commands.at(x);

            //Using string compare here since they're char * entries
            if(strncmp(com[0], "exit", 4) == 0) {
                exit(0);
            }

            //Main process thread
            pid_t i = fork();

            if(i < 0) { //Error
                perror("Failed to create child process");
                break;
            }
            else if(i == 0) { //Child process

                int result = execvp(com[0], &com[0]);
                if(result < 0) {
                    char result[100];
                    const char *error = "-rshell: ";
                    strcpy(result, error);
                    strcat(result, com[0]);
                    perror(result);
                }
                else {
                    exit(0);
                }
            }
            else { //Parent process
                int *status = nullptr;
                int stat = waitpid(i, status, 0); //Temp fix just to get child to run properly.
                if(stat < 0)
                    perror("Error waiting for child process");
            }
        }
	}
}
<commit_msg>Removing root rshell.cc file<commit_after><|endoftext|>


<commit_before>#pragma once

#include <string>
#include <iostream>
#include <sstream>
#include <tuple>

/* TODO
    All char types to be handled correctly.
    More succint dispatch for char types, probably SFINAE-based.
*/

namespace show{

    template<typename T>
    std::string show(const T& t);

    namespace _dtl {

        template<typename T>
        constexpr bool expand_to_false(){return false;}

        template<std::size_t> struct Nat{};
        template<typename...> struct TypeList{};

        template<typename T> using IsIterable =
            TypeList<decltype(std::begin(T{})),
                     decltype(std::end(T{})),
                     decltype(++std::begin(T{})),
                     decltype(*std::begin(T{})),
                     decltype(std::begin(T{}) != std::end(T{}))>;

        template<typename T> using IsTrivial =
            decltype(std::stringstream{}.operator<<(T{}));

        struct Iterable;
        struct Trivial;
        struct Undefined;
        struct Tuple;
        struct Pair;
        struct String;
        struct Char;

        template<typename T>
        struct GetFormat{
            template<typename U, typename = IsTrivial<U>>  static Trivial   check(void*);
            template<typename U, typename = IsIterable<U>> static Iterable  check(void*);
            template<typename>                             static Undefined check(...);
            using type = decltype(check<T>(nullptr));
        };

        template<typename A, typename B>
        struct GetFormat<std::pair<A, B>> {using type = Pair;};

        template<typename... TS>
        struct GetFormat<std::tuple<TS...>> {using type = Tuple;};

        template<typename C, typename T, typename A>
        struct GetFormat<std::basic_string<C, T, A>> {using type = String;};

        template<typename T, size_t N>
        struct GetFormat<T[N]> {using type = Iterable;};

        template<size_t N> struct GetFormat<char[N]>     {using type = String;};
        template<>         struct GetFormat<const char*> {using type = String;};
        template<>         struct GetFormat<char*>       {using type = String;};
        template<>         struct GetFormat<char>        {using type = Char;};

        struct Iterable{
            template<typename T>
            std::string operator()(const T& t){
                std::string res{};
                auto it = std::begin(t);
                auto finish = std::end(t);
                res += "[";
                if (it != finish){
                    res += show(*it);
                    ++it;
                    for (;it != finish; ++it){
                        res += ", ";
                        res += show(*it);
                    }
                }
                res += "]";
                return res;
            }
        };

        struct Trivial{
            template<typename T>
            std::string operator()(const T& t){
                std::stringstream fmt{};
                fmt.operator<<(t);
                return fmt.str();
            }
        };

        struct String{
            template<typename T>
            std::string operator()(const T& t){
                return "\"" + std::string(t) + "\"";
            }
        };

        struct Pair{
            template<typename A, typename B>
            std::string operator()(const std::pair<A, B>& p){
                return "(" + show(p.first) + ", " + show(p.second) + ")";
            }
        };

        struct Tuple{
            template <typename... TS>
            std::string operator()(const std::tuple<TS...>& tpl) {
                std::string res{};
                res += "(";
                helper(res, tpl, Nat<sizeof...(TS) - 1>{});
                res += ")";
                return res;
            }

            template<typename T, std::size_t N>
            void helper(std::string& res, const T &tpl, Nat<N>){
                helper(res, tpl, Nat<N-1>{});
                res += ", ";
                res += show(std::get<N>(tpl));
            }

            template<typename T>
            void helper(std::string& res, const T &tpl, Nat<0>){
                res += show(std::get<0>(tpl));
            }
        };

        struct Char{
            template<typename T>
            std::string operator()(const T& t){
                return std::string("'") + t + '\'';
            }
        };

        struct Undefined{
            template<typename T>
            std::string operator()(const T&){
                static_assert(expand_to_false<T>(), "Show undefined for type.");
                return "";
            }
        };

    } // namespace _dtl

    template<typename T>
    std::string show(const T& t){
        return typename _dtl::GetFormat<T>::type{}(t);
    }

    void print(){
        std::cout << std::endl;
    }

    template<typename T, typename... TS>
    void print(const T& t, const TS&... ts){
        std::cout << show(t) << ' ';
        print(ts...);
    }

} // namespace show
<commit_msg>rewrite show in extensible typeclass-style<commit_after>#pragma once

#include <type_traits>
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <tuple>

namespace show{

template<typename T>
struct Show {
    static std::string show(const T&){
        static_assert(expand_to_false<T>(), "no instance for class Show");
    }
private:
    template<typename>
    static constexpr bool expand_to_false(){return false;}
};

template<typename T>
struct Show_default{
    static std::string show(const T& x){
        std::stringstream out;
        out << x;
        return out.str();
    }
};

template<typename T>
std::string show(T&& x){
    return Show<T>::show(std::forward<T>(x));
};

template<typename T>
struct Show_fwd_iterable{
    static std::string show(const T& t){
        std::string res{};
        auto it = std::begin(t);
        auto finish = std::end(t);
        res += "[";
        if (it != finish){
            res += Show<decltype(*it)>::show(*it);
            ++it;
            for (;it != finish; ++it){
                res += ", ";
                res += Show<decltype(*it)>::show(*it);
            }
        }
        res += "]";
        return res;
    }
};

template<typename T>
struct Show_tuple{
    static std::string show(const T& t){
        std::string res{};
        res += '(';
        show_tuple_help(res, t, Nat<std::tuple_size<T>::value>{});
        res += ')';
        return res;
    }
private:
    template<size_t> struct Nat{};

    template<size_t i>
    static void show_tuple_help(std::string& res, const T& t, Nat<i>){
        show_tuple_help(res, t, Nat<i-1>{});
        res += Show<decltype(std::get<i-1>(t))>::show(std::get<i-1>(t));
        if (i != std::tuple_size<T>::value)
            res += ", ";
    }
    static void show_tuple_help(std::string&, const T&, Nat<0>){}
};

template<typename T> struct Show<const T>   : public Show<T> {};
template<typename T> struct Show<T&>        : public Show<T> {};
template<typename T> struct Show<T&&>       : public Show<T> {};
template<typename T> struct Show<const T&>  : public Show<T> {};
template<typename T> struct Show<const T&&> : public Show<T> {};

template<> struct Show<char>:           public Show_default<char> {};
template<> struct Show<char16_t>:       public Show_default<char16_t> {};
template<> struct Show<char32_t>:       public Show_default<char32_t> {};
template<> struct Show<wchar_t>:        public Show_default<wchar_t> {};
template<> struct Show<unsigned char>:  public Show_default<unsigned char> {};
template<> struct Show<short>:          public Show_default<short> {};
template<> struct Show<unsigned short>: public Show_default<unsigned short> {};
template<> struct Show<int>:            public Show_default<int> {};
template<> struct Show<unsigned>:       public Show_default<unsigned> {};
template<> struct Show<long>:           public Show_default<long> {};
template<> struct Show<unsigned long>:  public Show_default<unsigned long> {};
template<> struct Show<float>:          public Show_default<float> {};
template<> struct Show<double>:         public Show_default<double> {};
template<> struct Show<long double>:    public Show_default<long double> {};

template<size_t N, typename T>
struct Show<T[N]> : public Show_fwd_iterable<T[N]>{};

template<typename T, typename A>
struct Show<std::vector<T, A>> : public Show_fwd_iterable<std::vector<T, A>> {};

template<typename C, typename T, typename A>
struct Show<std::basic_string<C, T, A>> {
    static std::string show(const std::basic_string<C, T, A>& x){
        return '"' + x + '"';
    }
};

template<typename A, typename B>
struct Show<std::pair<A, B>> {
    static std::string show(const std::pair<A, B>& p){
        return "(" + Show<A>::show(p.first) + ", " + Show<B>::show(p.second) + ")";
    }
};

template<size_t N>
struct Show<char[N]> {
    static std::string show(char const(&s)[N]){
        return std::string("\"") + s + '"';
    }
};

template<>
struct Show<bool>{
    static std::string show(const bool& x){
        return x ? "true" : "false";
    }
};

template<typename...TS>
struct Show<std::tuple<TS...>> : public Show_tuple<std::tuple<TS...>> {};

void print(){
    std::cout << '\n';
}

template<typename T, typename...TS>
void print(T&& x, TS&&... xs){
    std::cout << show(std::forward<T>(x)) << " ";
    print(std::forward<TS>(xs)...);
}

} // namespace show

<|endoftext|>


<commit_before><commit_msg>3 Speedups for turning v8 strings into webcore strings<commit_after><|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include <functional>
#include <list>
#include <memory>
#include <string>

#include "testing/gtest/include/gtest/gtest.h"

#include "webrtc/audio_state.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/event.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/call.h"
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
#include "webrtc/system_wrappers/include/trace.h"
#include "webrtc/test/call_test.h"
#include "webrtc/test/direct_transport.h"
#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_decoder.h"
#include "webrtc/test/fake_encoder.h"
#include "webrtc/test/mock_voice_engine.h"
#include "webrtc/test/frame_generator_capturer.h"

namespace webrtc {
namespace {
// Note: If you consider to re-use this class, think twice and instead consider
// writing tests that don't depend on the logging system.
class LogObserver {
 public:
  LogObserver() { rtc::LogMessage::AddLogToStream(&callback_, rtc::LS_INFO); }

  ~LogObserver() { rtc::LogMessage::RemoveLogToStream(&callback_); }

  void PushExpectedLogLine(const std::string& expected_log_line) {
    callback_.PushExpectedLogLine(expected_log_line);
  }

  bool Wait() { return callback_.Wait(); }

 private:
  class Callback : public rtc::LogSink {
   public:
    Callback() : done_(false, false) {}

    void OnLogMessage(const std::string& message) override {
      rtc::CritScope lock(&crit_sect_);
      // Ignore log lines that are due to missing AST extensions, these are
      // logged when we switch back from AST to TOF until the wrapping bitrate
      // estimator gives up on using AST.
      if (message.find("BitrateEstimator") != std::string::npos &&
          message.find("packet is missing") == std::string::npos) {
        received_log_lines_.push_back(message);
      }

      int num_popped = 0;
      while (!received_log_lines_.empty() && !expected_log_lines_.empty()) {
        std::string a = received_log_lines_.front();
        std::string b = expected_log_lines_.front();
        received_log_lines_.pop_front();
        expected_log_lines_.pop_front();
        num_popped++;
        EXPECT_TRUE(a.find(b) != std::string::npos) << a << " != " << b;
      }
      if (expected_log_lines_.size() <= 0) {
        if (num_popped > 0) {
          done_.Set();
        }
        return;
      }
    }

    bool Wait() { return done_.Wait(test::CallTest::kDefaultTimeoutMs); }

    void PushExpectedLogLine(const std::string& expected_log_line) {
      rtc::CritScope lock(&crit_sect_);
      expected_log_lines_.push_back(expected_log_line);
    }

   private:
    typedef std::list<std::string> Strings;
    rtc::CriticalSection crit_sect_;
    Strings received_log_lines_ GUARDED_BY(crit_sect_);
    Strings expected_log_lines_ GUARDED_BY(crit_sect_);
    rtc::Event done_;
  };

  Callback callback_;
};
}  // namespace

static const int kTOFExtensionId = 4;
static const int kASTExtensionId = 5;

class BitrateEstimatorTest : public test::CallTest {
 public:
  BitrateEstimatorTest() : receive_config_(nullptr) {}

  virtual ~BitrateEstimatorTest() { EXPECT_TRUE(streams_.empty()); }

  virtual void SetUp() {
    AudioState::Config audio_state_config;
    audio_state_config.voice_engine = &mock_voice_engine_;
    Call::Config config;
    config.audio_state = AudioState::Create(audio_state_config);
    receiver_call_.reset(Call::Create(config));
    sender_call_.reset(Call::Create(config));

    send_transport_.reset(new test::DirectTransport(sender_call_.get()));
    send_transport_->SetReceiver(receiver_call_->Receiver());
    receive_transport_.reset(new test::DirectTransport(receiver_call_.get()));
    receive_transport_->SetReceiver(sender_call_->Receiver());

    video_send_config_ = VideoSendStream::Config(send_transport_.get());
    video_send_config_.rtp.ssrcs.push_back(kVideoSendSsrcs[0]);
    // Encoders will be set separately per stream.
    video_send_config_.encoder_settings.encoder = nullptr;
    video_send_config_.encoder_settings.payload_name = "FAKE";
    video_send_config_.encoder_settings.payload_type =
        kFakeVideoSendPayloadType;
    video_encoder_config_.streams = test::CreateVideoStreams(1);

    receive_config_ = VideoReceiveStream::Config(receive_transport_.get());
    // receive_config_.decoders will be set by every stream separately.
    receive_config_.rtp.remote_ssrc = video_send_config_.rtp.ssrcs[0];
    receive_config_.rtp.local_ssrc = kReceiverLocalVideoSsrc;
    receive_config_.rtp.remb = true;
    receive_config_.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
    receive_config_.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId));
  }

  virtual void TearDown() {
    std::for_each(streams_.begin(), streams_.end(),
                  std::mem_fun(&Stream::StopSending));

    send_transport_->StopSending();
    receive_transport_->StopSending();

    while (!streams_.empty()) {
      delete streams_.back();
      streams_.pop_back();
    }

    receiver_call_.reset();
    sender_call_.reset();
  }

 protected:
  friend class Stream;

  class Stream {
   public:
    Stream(BitrateEstimatorTest* test, bool receive_audio)
        : test_(test),
          is_sending_receiving_(false),
          send_stream_(nullptr),
          audio_receive_stream_(nullptr),
          video_receive_stream_(nullptr),
          frame_generator_capturer_(),
          fake_encoder_(Clock::GetRealTimeClock()),
          fake_decoder_() {
      test_->video_send_config_.rtp.ssrcs[0]++;
      test_->video_send_config_.encoder_settings.encoder = &fake_encoder_;
      send_stream_ = test_->sender_call_->CreateVideoSendStream(
          test_->video_send_config_, test_->video_encoder_config_);
      RTC_DCHECK_EQ(1u, test_->video_encoder_config_.streams.size());
      frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
          send_stream_->Input(), test_->video_encoder_config_.streams[0].width,
          test_->video_encoder_config_.streams[0].height, 30,
          Clock::GetRealTimeClock()));
      send_stream_->Start();
      frame_generator_capturer_->Start();

      if (receive_audio) {
        AudioReceiveStream::Config receive_config;
        receive_config.rtp.remote_ssrc = test_->video_send_config_.rtp.ssrcs[0];
        // Bogus non-default id to prevent hitting a RTC_DCHECK when creating
        // the AudioReceiveStream. Every receive stream has to correspond to
        // an underlying channel id.
        receive_config.voe_channel_id = 0;
        receive_config.rtp.extensions.push_back(
            RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId));
        audio_receive_stream_ =
            test_->receiver_call_->CreateAudioReceiveStream(receive_config);
      } else {
        VideoReceiveStream::Decoder decoder;
        decoder.decoder = &fake_decoder_;
        decoder.payload_type =
            test_->video_send_config_.encoder_settings.payload_type;
        decoder.payload_name =
            test_->video_send_config_.encoder_settings.payload_name;
        test_->receive_config_.decoders.clear();
        test_->receive_config_.decoders.push_back(decoder);
        test_->receive_config_.rtp.remote_ssrc =
            test_->video_send_config_.rtp.ssrcs[0];
        test_->receive_config_.rtp.local_ssrc++;
        video_receive_stream_ = test_->receiver_call_->CreateVideoReceiveStream(
            test_->receive_config_);
        video_receive_stream_->Start();
      }
      is_sending_receiving_ = true;
    }

    ~Stream() {
      EXPECT_FALSE(is_sending_receiving_);
      frame_generator_capturer_.reset(nullptr);
      test_->sender_call_->DestroyVideoSendStream(send_stream_);
      send_stream_ = nullptr;
      if (audio_receive_stream_) {
        test_->receiver_call_->DestroyAudioReceiveStream(audio_receive_stream_);
        audio_receive_stream_ = nullptr;
      }
      if (video_receive_stream_) {
        test_->receiver_call_->DestroyVideoReceiveStream(video_receive_stream_);
        video_receive_stream_ = nullptr;
      }
    }

    void StopSending() {
      if (is_sending_receiving_) {
        frame_generator_capturer_->Stop();
        send_stream_->Stop();
        if (video_receive_stream_) {
          video_receive_stream_->Stop();
        }
        is_sending_receiving_ = false;
      }
    }

   private:
    BitrateEstimatorTest* test_;
    bool is_sending_receiving_;
    VideoSendStream* send_stream_;
    AudioReceiveStream* audio_receive_stream_;
    VideoReceiveStream* video_receive_stream_;
    std::unique_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
    test::FakeEncoder fake_encoder_;
    test::FakeDecoder fake_decoder_;
  };

  testing::NiceMock<test::MockVoiceEngine> mock_voice_engine_;
  LogObserver receiver_log_;
  std::unique_ptr<test::DirectTransport> send_transport_;
  std::unique_ptr<test::DirectTransport> receive_transport_;
  std::unique_ptr<Call> sender_call_;
  std::unique_ptr<Call> receiver_call_;
  VideoReceiveStream::Config receive_config_;
  std::vector<Stream*> streams_;
};

static const char* kAbsSendTimeLog =
    "RemoteBitrateEstimatorAbsSendTime: Instantiating.";
static const char* kSingleStreamLog =
    "RemoteBitrateEstimatorSingleStream: Instantiating.";

TEST_F(BitrateEstimatorTest, InstantiatesTOFPerDefaultForVideo) {
  video_send_config_.rtp.extensions.push_back(
      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());
}

TEST_F(BitrateEstimatorTest, ImmediatelySwitchToASTForVideo) {
  video_send_config_.rtp.extensions.push_back(
      RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId));
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine("Switching to absolute send time RBE.");
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());
}

TEST_F(BitrateEstimatorTest, SwitchesToASTForVideo) {
  video_send_config_.rtp.extensions.push_back(
      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());

  video_send_config_.rtp.extensions[0] =
      RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine("Switching to absolute send time RBE.");
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());
}

TEST_F(BitrateEstimatorTest, SwitchesToASTThenBackToTOFForVideo) {
  video_send_config_.rtp.extensions.push_back(
      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());

  video_send_config_.rtp.extensions[0] =
      RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine("Switching to absolute send time RBE.");
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());

  video_send_config_.rtp.extensions[0] =
      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine(
      "WrappingBitrateEstimator: Switching to transmission time offset RBE.");
  streams_.push_back(new Stream(this, false));
  streams_[0]->StopSending();
  streams_[1]->StopSending();
  EXPECT_TRUE(receiver_log_.Wait());
}
}  // namespace webrtc
<commit_msg>Suppress a flaky test: SwitchesToASTThenBackToTOFForVideo.<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include <functional>
#include <list>
#include <memory>
#include <string>

#include "testing/gtest/include/gtest/gtest.h"

#include "webrtc/audio_state.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/event.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/call.h"
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
#include "webrtc/system_wrappers/include/trace.h"
#include "webrtc/test/call_test.h"
#include "webrtc/test/direct_transport.h"
#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_decoder.h"
#include "webrtc/test/fake_encoder.h"
#include "webrtc/test/mock_voice_engine.h"
#include "webrtc/test/frame_generator_capturer.h"

namespace webrtc {
namespace {
// Note: If you consider to re-use this class, think twice and instead consider
// writing tests that don't depend on the logging system.
class LogObserver {
 public:
  LogObserver() { rtc::LogMessage::AddLogToStream(&callback_, rtc::LS_INFO); }

  ~LogObserver() { rtc::LogMessage::RemoveLogToStream(&callback_); }

  void PushExpectedLogLine(const std::string& expected_log_line) {
    callback_.PushExpectedLogLine(expected_log_line);
  }

  bool Wait() { return callback_.Wait(); }

 private:
  class Callback : public rtc::LogSink {
   public:
    Callback() : done_(false, false) {}

    void OnLogMessage(const std::string& message) override {
      rtc::CritScope lock(&crit_sect_);
      // Ignore log lines that are due to missing AST extensions, these are
      // logged when we switch back from AST to TOF until the wrapping bitrate
      // estimator gives up on using AST.
      if (message.find("BitrateEstimator") != std::string::npos &&
          message.find("packet is missing") == std::string::npos) {
        received_log_lines_.push_back(message);
      }

      int num_popped = 0;
      while (!received_log_lines_.empty() && !expected_log_lines_.empty()) {
        std::string a = received_log_lines_.front();
        std::string b = expected_log_lines_.front();
        received_log_lines_.pop_front();
        expected_log_lines_.pop_front();
        num_popped++;
        EXPECT_TRUE(a.find(b) != std::string::npos) << a << " != " << b;
      }
      if (expected_log_lines_.size() <= 0) {
        if (num_popped > 0) {
          done_.Set();
        }
        return;
      }
    }

    bool Wait() { return done_.Wait(test::CallTest::kDefaultTimeoutMs); }

    void PushExpectedLogLine(const std::string& expected_log_line) {
      rtc::CritScope lock(&crit_sect_);
      expected_log_lines_.push_back(expected_log_line);
    }

   private:
    typedef std::list<std::string> Strings;
    rtc::CriticalSection crit_sect_;
    Strings received_log_lines_ GUARDED_BY(crit_sect_);
    Strings expected_log_lines_ GUARDED_BY(crit_sect_);
    rtc::Event done_;
  };

  Callback callback_;
};
}  // namespace

static const int kTOFExtensionId = 4;
static const int kASTExtensionId = 5;

class BitrateEstimatorTest : public test::CallTest {
 public:
  BitrateEstimatorTest() : receive_config_(nullptr) {}

  virtual ~BitrateEstimatorTest() { EXPECT_TRUE(streams_.empty()); }

  virtual void SetUp() {
    AudioState::Config audio_state_config;
    audio_state_config.voice_engine = &mock_voice_engine_;
    Call::Config config;
    config.audio_state = AudioState::Create(audio_state_config);
    receiver_call_.reset(Call::Create(config));
    sender_call_.reset(Call::Create(config));

    send_transport_.reset(new test::DirectTransport(sender_call_.get()));
    send_transport_->SetReceiver(receiver_call_->Receiver());
    receive_transport_.reset(new test::DirectTransport(receiver_call_.get()));
    receive_transport_->SetReceiver(sender_call_->Receiver());

    video_send_config_ = VideoSendStream::Config(send_transport_.get());
    video_send_config_.rtp.ssrcs.push_back(kVideoSendSsrcs[0]);
    // Encoders will be set separately per stream.
    video_send_config_.encoder_settings.encoder = nullptr;
    video_send_config_.encoder_settings.payload_name = "FAKE";
    video_send_config_.encoder_settings.payload_type =
        kFakeVideoSendPayloadType;
    video_encoder_config_.streams = test::CreateVideoStreams(1);

    receive_config_ = VideoReceiveStream::Config(receive_transport_.get());
    // receive_config_.decoders will be set by every stream separately.
    receive_config_.rtp.remote_ssrc = video_send_config_.rtp.ssrcs[0];
    receive_config_.rtp.local_ssrc = kReceiverLocalVideoSsrc;
    receive_config_.rtp.remb = true;
    receive_config_.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
    receive_config_.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId));
  }

  virtual void TearDown() {
    std::for_each(streams_.begin(), streams_.end(),
                  std::mem_fun(&Stream::StopSending));

    send_transport_->StopSending();
    receive_transport_->StopSending();

    while (!streams_.empty()) {
      delete streams_.back();
      streams_.pop_back();
    }

    receiver_call_.reset();
    sender_call_.reset();
  }

 protected:
  friend class Stream;

  class Stream {
   public:
    Stream(BitrateEstimatorTest* test, bool receive_audio)
        : test_(test),
          is_sending_receiving_(false),
          send_stream_(nullptr),
          audio_receive_stream_(nullptr),
          video_receive_stream_(nullptr),
          frame_generator_capturer_(),
          fake_encoder_(Clock::GetRealTimeClock()),
          fake_decoder_() {
      test_->video_send_config_.rtp.ssrcs[0]++;
      test_->video_send_config_.encoder_settings.encoder = &fake_encoder_;
      send_stream_ = test_->sender_call_->CreateVideoSendStream(
          test_->video_send_config_, test_->video_encoder_config_);
      RTC_DCHECK_EQ(1u, test_->video_encoder_config_.streams.size());
      frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
          send_stream_->Input(), test_->video_encoder_config_.streams[0].width,
          test_->video_encoder_config_.streams[0].height, 30,
          Clock::GetRealTimeClock()));
      send_stream_->Start();
      frame_generator_capturer_->Start();

      if (receive_audio) {
        AudioReceiveStream::Config receive_config;
        receive_config.rtp.remote_ssrc = test_->video_send_config_.rtp.ssrcs[0];
        // Bogus non-default id to prevent hitting a RTC_DCHECK when creating
        // the AudioReceiveStream. Every receive stream has to correspond to
        // an underlying channel id.
        receive_config.voe_channel_id = 0;
        receive_config.rtp.extensions.push_back(
            RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId));
        audio_receive_stream_ =
            test_->receiver_call_->CreateAudioReceiveStream(receive_config);
      } else {
        VideoReceiveStream::Decoder decoder;
        decoder.decoder = &fake_decoder_;
        decoder.payload_type =
            test_->video_send_config_.encoder_settings.payload_type;
        decoder.payload_name =
            test_->video_send_config_.encoder_settings.payload_name;
        test_->receive_config_.decoders.clear();
        test_->receive_config_.decoders.push_back(decoder);
        test_->receive_config_.rtp.remote_ssrc =
            test_->video_send_config_.rtp.ssrcs[0];
        test_->receive_config_.rtp.local_ssrc++;
        video_receive_stream_ = test_->receiver_call_->CreateVideoReceiveStream(
            test_->receive_config_);
        video_receive_stream_->Start();
      }
      is_sending_receiving_ = true;
    }

    ~Stream() {
      EXPECT_FALSE(is_sending_receiving_);
      frame_generator_capturer_.reset(nullptr);
      test_->sender_call_->DestroyVideoSendStream(send_stream_);
      send_stream_ = nullptr;
      if (audio_receive_stream_) {
        test_->receiver_call_->DestroyAudioReceiveStream(audio_receive_stream_);
        audio_receive_stream_ = nullptr;
      }
      if (video_receive_stream_) {
        test_->receiver_call_->DestroyVideoReceiveStream(video_receive_stream_);
        video_receive_stream_ = nullptr;
      }
    }

    void StopSending() {
      if (is_sending_receiving_) {
        frame_generator_capturer_->Stop();
        send_stream_->Stop();
        if (video_receive_stream_) {
          video_receive_stream_->Stop();
        }
        is_sending_receiving_ = false;
      }
    }

   private:
    BitrateEstimatorTest* test_;
    bool is_sending_receiving_;
    VideoSendStream* send_stream_;
    AudioReceiveStream* audio_receive_stream_;
    VideoReceiveStream* video_receive_stream_;
    std::unique_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
    test::FakeEncoder fake_encoder_;
    test::FakeDecoder fake_decoder_;
  };

  testing::NiceMock<test::MockVoiceEngine> mock_voice_engine_;
  LogObserver receiver_log_;
  std::unique_ptr<test::DirectTransport> send_transport_;
  std::unique_ptr<test::DirectTransport> receive_transport_;
  std::unique_ptr<Call> sender_call_;
  std::unique_ptr<Call> receiver_call_;
  VideoReceiveStream::Config receive_config_;
  std::vector<Stream*> streams_;
};

static const char* kAbsSendTimeLog =
    "RemoteBitrateEstimatorAbsSendTime: Instantiating.";
static const char* kSingleStreamLog =
    "RemoteBitrateEstimatorSingleStream: Instantiating.";

TEST_F(BitrateEstimatorTest, InstantiatesTOFPerDefaultForVideo) {
  video_send_config_.rtp.extensions.push_back(
      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());
}

TEST_F(BitrateEstimatorTest, ImmediatelySwitchToASTForVideo) {
  video_send_config_.rtp.extensions.push_back(
      RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId));
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine("Switching to absolute send time RBE.");
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());
}

TEST_F(BitrateEstimatorTest, SwitchesToASTForVideo) {
  video_send_config_.rtp.extensions.push_back(
      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());

  video_send_config_.rtp.extensions[0] =
      RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine("Switching to absolute send time RBE.");
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());
}

// Fails when run with ASan. See webrtc:5790.
#if defined(ADDRESS_SANITIZER)
#define MAYBE_SwitchesToASTThenBackToTOFForVideo \
    DISABLED_SwitchesToASTThenBackToTOFForVideo
#else
#define MAYBE_SwitchesToASTThenBackToTOFForVideo \
    SwitchesToASTThenBackToTOFForVideo
#endif
TEST_F(BitrateEstimatorTest, MAYBE_SwitchesToASTThenBackToTOFForVideo) {
  video_send_config_.rtp.extensions.push_back(
      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine(kSingleStreamLog);
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());

  video_send_config_.rtp.extensions[0] =
      RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine("Switching to absolute send time RBE.");
  streams_.push_back(new Stream(this, false));
  EXPECT_TRUE(receiver_log_.Wait());

  video_send_config_.rtp.extensions[0] =
      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId);
  receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
  receiver_log_.PushExpectedLogLine(
      "WrappingBitrateEstimator: Switching to transmission time offset RBE.");
  streams_.push_back(new Stream(this, false));
  streams_[0]->StopSending();
  streams_[1]->StopSending();
  EXPECT_TRUE(receiver_log_.Wait());
}
}  // namespace webrtc
<|endoftext|>


<commit_before>//===--- CGTemporaries.cpp - Emit LLVM Code for C++ temporaries -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with C++ code generation of temporaries
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
using namespace clang;
using namespace CodeGen;

void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary,
                                       llvm::Value *Ptr) {
  assert((LiveTemporaries.empty() ||
          LiveTemporaries.back().ThisPtr != Ptr) &&
         "Pushed the same temporary twice; AST is likely wrong");
  llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor");

  llvm::Value *CondPtr = 0;

  // Check if temporaries need to be conditional. If so, we'll create a
  // condition boolean, initialize it to 0 and
  if (ConditionalBranchLevel != 0) {
    CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond");

    // Initialize it to false. This initialization takes place right after
    // the alloca insert point.
    llvm::StoreInst *SI =
      new llvm::StoreInst(llvm::ConstantInt::getFalse(VMContext), CondPtr);
    llvm::BasicBlock *Block = AllocaInsertPt->getParent();
    Block->getInstList().insertAfter((llvm::Instruction *)AllocaInsertPt, SI);

    // Now set it to true.
    Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), CondPtr);
  }

  LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock,
                                                 CondPtr));

  PushCleanupBlock(DtorBlock);

  if (Exceptions) {
    const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();
    llvm::BasicBlock *CondEnd = 0;

    EHCleanupBlock Cleanup(*this);

    // If this is a conditional temporary, we need to check the condition
    // boolean and only call the destructor if it's true.
    if (Info.CondPtr) {
      llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
      CondEnd = createBasicBlock("cond.dtor.end");

      llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
      Builder.CreateCondBr(Cond, CondBlock, CondEnd);
      EmitBlock(CondBlock);
    }

    EmitCXXDestructorCall(Info.Temporary->getDestructor(),
                          Dtor_Complete, Info.ThisPtr);

    if (CondEnd) {
      // Reset the condition. to false.
      Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr);
      EmitBlock(CondEnd);
    }
  }
}

void CodeGenFunction::PopCXXTemporary() {
  const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();

  CleanupBlockInfo CleanupInfo = PopCleanupBlock();
  assert(CleanupInfo.CleanupBlock == Info.DtorBlock &&
         "Cleanup block mismatch!");
  assert(!CleanupInfo.SwitchBlock &&
         "Should not have a switch block for temporary cleanup!");
  assert(!CleanupInfo.EndBlock &&
         "Should not have an end block for temporary cleanup!");

  llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
  if (CurBB && !CurBB->getTerminator() &&
      Info.DtorBlock->getNumUses() == 0) {
    CurBB->getInstList().splice(CurBB->end(), Info.DtorBlock->getInstList());
    delete Info.DtorBlock;
  } else
    EmitBlock(Info.DtorBlock);

  llvm::BasicBlock *CondEnd = 0;

  // If this is a conditional temporary, we need to check the condition
  // boolean and only call the destructor if it's true.
  if (Info.CondPtr) {
    llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
    CondEnd = createBasicBlock("cond.dtor.end");

    llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
    Builder.CreateCondBr(Cond, CondBlock, CondEnd);
    EmitBlock(CondBlock);
  }

  EmitCXXDestructorCall(Info.Temporary->getDestructor(),
                        Dtor_Complete, Info.ThisPtr);

  if (CondEnd) {
    // Reset the condition. to false.
    Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr);
    EmitBlock(CondEnd);
  }

  LiveTemporaries.pop_back();
}

RValue
CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
                                            llvm::Value *AggLoc,
                                            bool IsAggLocVolatile,
                                            bool IsInitializer) {
  // Keep track of the current cleanup stack depth.
  size_t CleanupStackDepth = CleanupEntries.size();
  (void) CleanupStackDepth;

  unsigned OldNumLiveTemporaries = LiveTemporaries.size();

  RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile,
                          /*IgnoreResult=*/false, IsInitializer);

  // Pop temporaries.
  while (LiveTemporaries.size() > OldNumLiveTemporaries)
    PopCXXTemporary();

  assert(CleanupEntries.size() == CleanupStackDepth &&
         "Cleanup size mismatch!");

  return RV;
}

LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue(
                                              const CXXExprWithTemporaries *E) {
  // Keep track of the current cleanup stack depth.
  size_t CleanupStackDepth = CleanupEntries.size();
  (void) CleanupStackDepth;

  unsigned OldNumLiveTemporaries = LiveTemporaries.size();

  LValue LV = EmitLValue(E->getSubExpr());

  // Pop temporaries.
  while (LiveTemporaries.size() > OldNumLiveTemporaries)
    PopCXXTemporary();

  assert(CleanupEntries.size() == CleanupStackDepth &&
         "Cleanup size mismatch!");

  return LV;
}
<commit_msg>Fix double-destruction assertion to account for temporaries in conditionals<commit_after>//===--- CGTemporaries.cpp - Emit LLVM Code for C++ temporaries -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with C++ code generation of temporaries
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
using namespace clang;
using namespace CodeGen;

void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary,
                                       llvm::Value *Ptr) {
  assert((LiveTemporaries.empty() ||
          LiveTemporaries.back().ThisPtr != Ptr ||
          ConditionalBranchLevel) &&
         "Pushed the same temporary twice; AST is likely wrong");
  llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor");

  llvm::Value *CondPtr = 0;

  // Check if temporaries need to be conditional. If so, we'll create a
  // condition boolean, initialize it to 0 and
  if (ConditionalBranchLevel != 0) {
    CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond");

    // Initialize it to false. This initialization takes place right after
    // the alloca insert point.
    llvm::StoreInst *SI =
      new llvm::StoreInst(llvm::ConstantInt::getFalse(VMContext), CondPtr);
    llvm::BasicBlock *Block = AllocaInsertPt->getParent();
    Block->getInstList().insertAfter((llvm::Instruction *)AllocaInsertPt, SI);

    // Now set it to true.
    Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), CondPtr);
  }

  LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock,
                                                 CondPtr));

  PushCleanupBlock(DtorBlock);

  if (Exceptions) {
    const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();
    llvm::BasicBlock *CondEnd = 0;

    EHCleanupBlock Cleanup(*this);

    // If this is a conditional temporary, we need to check the condition
    // boolean and only call the destructor if it's true.
    if (Info.CondPtr) {
      llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
      CondEnd = createBasicBlock("cond.dtor.end");

      llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
      Builder.CreateCondBr(Cond, CondBlock, CondEnd);
      EmitBlock(CondBlock);
    }

    EmitCXXDestructorCall(Info.Temporary->getDestructor(),
                          Dtor_Complete, Info.ThisPtr);

    if (CondEnd) {
      // Reset the condition. to false.
      Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr);
      EmitBlock(CondEnd);
    }
  }
}

void CodeGenFunction::PopCXXTemporary() {
  const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();

  CleanupBlockInfo CleanupInfo = PopCleanupBlock();
  assert(CleanupInfo.CleanupBlock == Info.DtorBlock &&
         "Cleanup block mismatch!");
  assert(!CleanupInfo.SwitchBlock &&
         "Should not have a switch block for temporary cleanup!");
  assert(!CleanupInfo.EndBlock &&
         "Should not have an end block for temporary cleanup!");

  llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
  if (CurBB && !CurBB->getTerminator() &&
      Info.DtorBlock->getNumUses() == 0) {
    CurBB->getInstList().splice(CurBB->end(), Info.DtorBlock->getInstList());
    delete Info.DtorBlock;
  } else
    EmitBlock(Info.DtorBlock);

  llvm::BasicBlock *CondEnd = 0;

  // If this is a conditional temporary, we need to check the condition
  // boolean and only call the destructor if it's true.
  if (Info.CondPtr) {
    llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
    CondEnd = createBasicBlock("cond.dtor.end");

    llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
    Builder.CreateCondBr(Cond, CondBlock, CondEnd);
    EmitBlock(CondBlock);
  }

  EmitCXXDestructorCall(Info.Temporary->getDestructor(),
                        Dtor_Complete, Info.ThisPtr);

  if (CondEnd) {
    // Reset the condition. to false.
    Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr);
    EmitBlock(CondEnd);
  }

  LiveTemporaries.pop_back();
}

RValue
CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
                                            llvm::Value *AggLoc,
                                            bool IsAggLocVolatile,
                                            bool IsInitializer) {
  // Keep track of the current cleanup stack depth.
  size_t CleanupStackDepth = CleanupEntries.size();
  (void) CleanupStackDepth;

  unsigned OldNumLiveTemporaries = LiveTemporaries.size();

  RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile,
                          /*IgnoreResult=*/false, IsInitializer);

  // Pop temporaries.
  while (LiveTemporaries.size() > OldNumLiveTemporaries)
    PopCXXTemporary();

  assert(CleanupEntries.size() == CleanupStackDepth &&
         "Cleanup size mismatch!");

  return RV;
}

LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue(
                                              const CXXExprWithTemporaries *E) {
  // Keep track of the current cleanup stack depth.
  size_t CleanupStackDepth = CleanupEntries.size();
  (void) CleanupStackDepth;

  unsigned OldNumLiveTemporaries = LiveTemporaries.size();

  LValue LV = EmitLValue(E->getSubExpr());

  // Pop temporaries.
  while (LiveTemporaries.size() > OldNumLiveTemporaries)
    PopCXXTemporary();

  assert(CleanupEntries.size() == CleanupStackDepth &&
         "Cleanup size mismatch!");

  return LV;
}
<|endoftext|>


<commit_before>//===-- LiveVariables.cpp - Live Variable Analysis for Machine Code -------===//
//
// This file implements the LiveVariable analysis pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/CFG.h"
#include "Support/DepthFirstIterator.h"

static RegisterAnalysis<LiveVariables> X("livevars", "Live Variable Analysis");

void LiveVariables::MarkVirtRegAliveInBlock(VarInfo &VRInfo,
					    const BasicBlock *BB) {
  const std::pair<MachineBasicBlock*,unsigned> &Info = BBMap.find(BB)->second;
  MachineBasicBlock *MBB = Info.first;
  unsigned BBNum = Info.second;

  // Check to see if this basic block is one of the killing blocks.  If so,
  // remove it...
  for (unsigned i = 0, e = VRInfo.Kills.size(); i != e; ++i)
    if (VRInfo.Kills[i].first == MBB) {
      VRInfo.Kills.erase(VRInfo.Kills.begin()+i);  // Erase entry
      break;
    }

  if (MBB == VRInfo.DefBlock) return;  // Terminate recursion

  if (VRInfo.AliveBlocks.size() <= BBNum)
    VRInfo.AliveBlocks.resize(BBNum+1);  // Make space...

  if (VRInfo.AliveBlocks[BBNum])
    return;  // We already know the block is live

  // Mark the variable known alive in this bb
  VRInfo.AliveBlocks[BBNum] = true;

  for (pred_const_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
    MarkVirtRegAliveInBlock(VRInfo, *PI);
}

void LiveVariables::HandleVirtRegUse(VarInfo &VRInfo, MachineBasicBlock *MBB,
				     MachineInstr *MI) {
  // Check to see if this basic block is already a kill block...
  if (!VRInfo.Kills.empty() && VRInfo.Kills.back().first == MBB) {
    // Yes, this register is killed in this basic block already.  Increase the
    // live range by updating the kill instruction.
    VRInfo.Kills.back().second = MI;
    return;
  }

#ifndef NDEBUG
  for (unsigned i = 0, e = VRInfo.Kills.size(); i != e; ++i)
    assert(VRInfo.Kills[i].first != MBB && "entry should be at end!");
#endif

  assert(MBB != VRInfo.DefBlock && "Should have kill for defblock!");

  // Add a new kill entry for this basic block.
  VRInfo.Kills.push_back(std::make_pair(MBB, MI));

  // Update all dominating blocks to mark them known live.
  const BasicBlock *BB = MBB->getBasicBlock();
  for (pred_const_iterator PI = pred_begin(BB), E = pred_end(BB);
       PI != E; ++PI)
    MarkVirtRegAliveInBlock(VRInfo, *PI);
}

void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr *MI) {
  if (PhysRegInfo[Reg]) {
    PhysRegInfo[Reg] = MI;
    PhysRegUsed[Reg] = true;
  } else if (const unsigned *AliasSet = RegInfo->getAliasSet(Reg)) {
    for (; unsigned NReg = AliasSet[0]; ++AliasSet)
      if (MachineInstr *LastUse = PhysRegInfo[NReg]) {
	PhysRegInfo[NReg] = MI;
	PhysRegUsed[NReg] = true;
      }
  }
}

void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) {
  // Does this kill a previous version of this register?
  if (MachineInstr *LastUse = PhysRegInfo[Reg]) {
    if (PhysRegUsed[Reg])
      RegistersKilled.insert(std::make_pair(LastUse, Reg));
    else
      RegistersDead.insert(std::make_pair(LastUse, Reg));
  } else if (const unsigned *AliasSet = RegInfo->getAliasSet(Reg)) {
    for (; unsigned NReg = AliasSet[0]; ++AliasSet)
      if (MachineInstr *LastUse = PhysRegInfo[NReg]) {
	if (PhysRegUsed[NReg])
	  RegistersKilled.insert(std::make_pair(LastUse, NReg));
	else
	  RegistersDead.insert(std::make_pair(LastUse, NReg));
	PhysRegInfo[NReg] = 0;  // Kill the aliased register
      }
  }
  PhysRegInfo[Reg] = MI;
  PhysRegUsed[Reg] = false;
}

bool LiveVariables::runOnMachineFunction(MachineFunction &MF) {
  // Build BBMap...
  unsigned BBNum = 0;
  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
    BBMap[I->getBasicBlock()] = std::make_pair(I, BBNum++);

  // PhysRegInfo - Keep track of which instruction was the last use of a
  // physical register.  This is a purely local property, because all physical
  // register references as presumed dead across basic blocks.
  //
  MachineInstr *PhysRegInfoA[MRegisterInfo::FirstVirtualRegister];
  bool          PhysRegUsedA[MRegisterInfo::FirstVirtualRegister];
  std::fill(PhysRegInfoA, PhysRegInfoA+MRegisterInfo::FirstVirtualRegister,
	    (MachineInstr*)0);
  PhysRegInfo = PhysRegInfoA;
  PhysRegUsed = PhysRegUsedA;

  const TargetInstrInfo &TII = MF.getTarget().getInstrInfo();
  RegInfo = MF.getTarget().getRegisterInfo();

  /// Get some space for a respectable number of registers...
  VirtRegInfo.resize(64);

  // Calculate live variable information in depth first order on the CFG of the
  // function.  This guarantees that we will see the definition of a virtual
  // register before its uses due to dominance properties of SSA (except for PHI
  // nodes, which are treated as a special case).
  //
  const BasicBlock *Entry = MF.getFunction()->begin();
  for (df_iterator<const BasicBlock*> DFI = df_begin(Entry), E = df_end(Entry);
       DFI != E; ++DFI) {
    const BasicBlock *BB = *DFI;
    std::pair<MachineBasicBlock*, unsigned> &BBRec = BBMap.find(BB)->second;
    MachineBasicBlock *MBB = BBRec.first;
    unsigned BBNum = BBRec.second;

    // Loop over all of the instructions, processing them.
    for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
	 I != E; ++I) {
      MachineInstr *MI = *I;
      const TargetInstrDescriptor &MID = TII.get(MI->getOpcode());

      // Process all of the operands of the instruction...
      unsigned NumOperandsToProcess = MI->getNumOperands();

      // Unless it is a PHI node.  In this case, ONLY process the DEF, not any
      // of the uses.  They will be handled in other basic blocks.
      if (MI->getOpcode() == TargetInstrInfo::PHI)
	NumOperandsToProcess = 1;

      // Loop over implicit uses, using them.
      if (const unsigned *ImplicitUses = MID.ImplicitUses)
	for (unsigned i = 0; ImplicitUses[i]; ++i)
	  HandlePhysRegUse(ImplicitUses[i], MI);

      // Process all explicit uses...
      for (unsigned i = 0; i != NumOperandsToProcess; ++i) {
	MachineOperand &MO = MI->getOperand(i);
	if (MO.opIsUse() || MO.opIsDefAndUse()) {
	  if (MO.isVirtualRegister() && !MO.getVRegValueOrNull()) {
	    unsigned RegIdx = MO.getReg()-MRegisterInfo::FirstVirtualRegister;
	    HandleVirtRegUse(getVarInfo(RegIdx), MBB, MI);
	  } else if (MO.isPhysicalRegister() && MO.getReg() != 0
		   /// FIXME: This is a gross hack, due to us not being able to
		   /// say that some registers are defined on entry to the
		   /// function.  5 = ESP
&& MO.getReg() != 5
) {
	    HandlePhysRegUse(MO.getReg(), MI);
	  }
	}
      }

      // Loop over implicit defs, defining them.
      if (const unsigned *ImplicitDefs = MID.ImplicitDefs)
	for (unsigned i = 0; ImplicitDefs[i]; ++i)
	  HandlePhysRegDef(ImplicitDefs[i], MI);

      // Process all explicit defs...
      for (unsigned i = 0; i != NumOperandsToProcess; ++i) {
	MachineOperand &MO = MI->getOperand(i);
	if (MO.opIsDef() || MO.opIsDefAndUse()) {
	  if (MO.isVirtualRegister()) {
	    unsigned RegIdx = MO.getReg()-MRegisterInfo::FirstVirtualRegister;
	    VarInfo &VRInfo = getVarInfo(RegIdx);

	    assert(VRInfo.DefBlock == 0 && "Variable multiply defined!");
	    VRInfo.DefBlock = MBB;                           // Created here...
	    VRInfo.DefInst = MI;
	    VRInfo.Kills.push_back(std::make_pair(MBB, MI)); // Defaults to dead
	  } else if (MO.isPhysicalRegister() && MO.getReg() != 0
		   /// FIXME: This is a gross hack, due to us not being able to
		   /// say that some registers are defined on entry to the
		   /// function.  5 = ESP
&& MO.getReg() != 5
) {
	    HandlePhysRegDef(MO.getReg(), MI);
	  }
	}
      }
    }

    // Handle any virtual assignments from PHI nodes which might be at the
    // bottom of this basic block.  We check all of our successor blocks to see
    // if they have PHI nodes, and if so, we simulate an assignment at the end
    // of the current block.
    for (succ_const_iterator SI = succ_begin(BB), E = succ_end(BB);
         SI != E; ++SI) {
      MachineBasicBlock *Succ = BBMap.find(*SI)->second.first;

      // PHI nodes are guaranteed to be at the top of the block...
      for (MachineBasicBlock::iterator I = Succ->begin(), E = Succ->end();
	   I != E && (*I)->getOpcode() == TargetInstrInfo::PHI; ++I) {
        MachineInstr *MI = *I;
	for (unsigned i = 1; ; i += 2)
	  if (MI->getOperand(i+1).getMachineBasicBlock() == MBB) {
	    MachineOperand &MO = MI->getOperand(i);
	    if (!MO.getVRegValueOrNull()) {
	      unsigned RegIdx = MO.getReg()-MRegisterInfo::FirstVirtualRegister;
	      VarInfo &VRInfo = getVarInfo(RegIdx);

	      // Only mark it alive only in the block we are representing...
	      MarkVirtRegAliveInBlock(VRInfo, BB);
	      break;   // Found the PHI entry for this block...
	    }
	  }
      }
    }

    // Loop over PhysRegInfo, killing any registers that are available at the
    // end of the basic block.  This also resets the PhysRegInfo map.
    for (unsigned i = 0, e = MRegisterInfo::FirstVirtualRegister; i != e; ++i)
      if (PhysRegInfo[i])
	HandlePhysRegDef(i, 0);
  }

  BBMap.clear();

  // Convert the information we have gathered into VirtRegInfo and transform it
  // into a form usable by RegistersKilled.
  //
  for (unsigned i = 0, e = VirtRegInfo.size(); i != e; ++i)
    for (unsigned j = 0, e = VirtRegInfo[i].Kills.size(); j != e; ++j) {
      if (VirtRegInfo[i].Kills[j].second == VirtRegInfo[i].DefInst)
	RegistersDead.insert(std::make_pair(VirtRegInfo[i].Kills[j].second,
		    i + MRegisterInfo::FirstVirtualRegister));

      else
	RegistersKilled.insert(std::make_pair(VirtRegInfo[i].Kills[j].second,
		    i + MRegisterInfo::FirstVirtualRegister));
    }

  return false;
}
<commit_msg>Remove hideously nasty hack<commit_after>//===-- LiveVariables.cpp - Live Variable Analysis for Machine Code -------===//
//
// This file implements the LiveVariable analysis pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/CFG.h"
#include "Support/DepthFirstIterator.h"

static RegisterAnalysis<LiveVariables> X("livevars", "Live Variable Analysis");

void LiveVariables::MarkVirtRegAliveInBlock(VarInfo &VRInfo,
					    const BasicBlock *BB) {
  const std::pair<MachineBasicBlock*,unsigned> &Info = BBMap.find(BB)->second;
  MachineBasicBlock *MBB = Info.first;
  unsigned BBNum = Info.second;

  // Check to see if this basic block is one of the killing blocks.  If so,
  // remove it...
  for (unsigned i = 0, e = VRInfo.Kills.size(); i != e; ++i)
    if (VRInfo.Kills[i].first == MBB) {
      VRInfo.Kills.erase(VRInfo.Kills.begin()+i);  // Erase entry
      break;
    }

  if (MBB == VRInfo.DefBlock) return;  // Terminate recursion

  if (VRInfo.AliveBlocks.size() <= BBNum)
    VRInfo.AliveBlocks.resize(BBNum+1);  // Make space...

  if (VRInfo.AliveBlocks[BBNum])
    return;  // We already know the block is live

  // Mark the variable known alive in this bb
  VRInfo.AliveBlocks[BBNum] = true;

  for (pred_const_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
    MarkVirtRegAliveInBlock(VRInfo, *PI);
}

void LiveVariables::HandleVirtRegUse(VarInfo &VRInfo, MachineBasicBlock *MBB,
				     MachineInstr *MI) {
  // Check to see if this basic block is already a kill block...
  if (!VRInfo.Kills.empty() && VRInfo.Kills.back().first == MBB) {
    // Yes, this register is killed in this basic block already.  Increase the
    // live range by updating the kill instruction.
    VRInfo.Kills.back().second = MI;
    return;
  }

#ifndef NDEBUG
  for (unsigned i = 0, e = VRInfo.Kills.size(); i != e; ++i)
    assert(VRInfo.Kills[i].first != MBB && "entry should be at end!");
#endif

  assert(MBB != VRInfo.DefBlock && "Should have kill for defblock!");

  // Add a new kill entry for this basic block.
  VRInfo.Kills.push_back(std::make_pair(MBB, MI));

  // Update all dominating blocks to mark them known live.
  const BasicBlock *BB = MBB->getBasicBlock();
  for (pred_const_iterator PI = pred_begin(BB), E = pred_end(BB);
       PI != E; ++PI)
    MarkVirtRegAliveInBlock(VRInfo, *PI);
}

void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr *MI) {
  if (PhysRegInfo[Reg]) {
    PhysRegInfo[Reg] = MI;
    PhysRegUsed[Reg] = true;
  } else if (const unsigned *AliasSet = RegInfo->getAliasSet(Reg)) {
    for (; unsigned NReg = AliasSet[0]; ++AliasSet)
      if (MachineInstr *LastUse = PhysRegInfo[NReg]) {
	PhysRegInfo[NReg] = MI;
	PhysRegUsed[NReg] = true;
      }
  }
}

void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) {
  // Does this kill a previous version of this register?
  if (MachineInstr *LastUse = PhysRegInfo[Reg]) {
    if (PhysRegUsed[Reg])
      RegistersKilled.insert(std::make_pair(LastUse, Reg));
    else
      RegistersDead.insert(std::make_pair(LastUse, Reg));
  } else if (const unsigned *AliasSet = RegInfo->getAliasSet(Reg)) {
    for (; unsigned NReg = AliasSet[0]; ++AliasSet)
      if (MachineInstr *LastUse = PhysRegInfo[NReg]) {
	if (PhysRegUsed[NReg])
	  RegistersKilled.insert(std::make_pair(LastUse, NReg));
	else
	  RegistersDead.insert(std::make_pair(LastUse, NReg));
	PhysRegInfo[NReg] = 0;  // Kill the aliased register
      }
  }
  PhysRegInfo[Reg] = MI;
  PhysRegUsed[Reg] = false;
}

bool LiveVariables::runOnMachineFunction(MachineFunction &MF) {
  // Build BBMap...
  unsigned BBNum = 0;
  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
    BBMap[I->getBasicBlock()] = std::make_pair(I, BBNum++);

  // PhysRegInfo - Keep track of which instruction was the last use of a
  // physical register.  This is a purely local property, because all physical
  // register references as presumed dead across basic blocks.
  //
  MachineInstr *PhysRegInfoA[MRegisterInfo::FirstVirtualRegister];
  bool          PhysRegUsedA[MRegisterInfo::FirstVirtualRegister];
  std::fill(PhysRegInfoA, PhysRegInfoA+MRegisterInfo::FirstVirtualRegister,
	    (MachineInstr*)0);
  PhysRegInfo = PhysRegInfoA;
  PhysRegUsed = PhysRegUsedA;

  const TargetInstrInfo &TII = MF.getTarget().getInstrInfo();
  RegInfo = MF.getTarget().getRegisterInfo();

  /// Get some space for a respectable number of registers...
  VirtRegInfo.resize(64);

  // Calculate live variable information in depth first order on the CFG of the
  // function.  This guarantees that we will see the definition of a virtual
  // register before its uses due to dominance properties of SSA (except for PHI
  // nodes, which are treated as a special case).
  //
  const BasicBlock *Entry = MF.getFunction()->begin();
  for (df_iterator<const BasicBlock*> DFI = df_begin(Entry), E = df_end(Entry);
       DFI != E; ++DFI) {
    const BasicBlock *BB = *DFI;
    std::pair<MachineBasicBlock*, unsigned> &BBRec = BBMap.find(BB)->second;
    MachineBasicBlock *MBB = BBRec.first;
    unsigned BBNum = BBRec.second;

    // Loop over all of the instructions, processing them.
    for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
	 I != E; ++I) {
      MachineInstr *MI = *I;
      const TargetInstrDescriptor &MID = TII.get(MI->getOpcode());

      // Process all of the operands of the instruction...
      unsigned NumOperandsToProcess = MI->getNumOperands();

      // Unless it is a PHI node.  In this case, ONLY process the DEF, not any
      // of the uses.  They will be handled in other basic blocks.
      if (MI->getOpcode() == TargetInstrInfo::PHI)
	NumOperandsToProcess = 1;

      // Loop over implicit uses, using them.
      if (const unsigned *ImplicitUses = MID.ImplicitUses)
	for (unsigned i = 0; ImplicitUses[i]; ++i)
	  HandlePhysRegUse(ImplicitUses[i], MI);

      // Process all explicit uses...
      for (unsigned i = 0; i != NumOperandsToProcess; ++i) {
	MachineOperand &MO = MI->getOperand(i);
	if (MO.opIsUse() || MO.opIsDefAndUse()) {
	  if (MO.isVirtualRegister() && !MO.getVRegValueOrNull()) {
	    unsigned RegIdx = MO.getReg()-MRegisterInfo::FirstVirtualRegister;
	    HandleVirtRegUse(getVarInfo(RegIdx), MBB, MI);
	  } else if (MO.isPhysicalRegister() && MO.getReg() != 0) {
	    HandlePhysRegUse(MO.getReg(), MI);
	  }
	}
      }

      // Loop over implicit defs, defining them.
      if (const unsigned *ImplicitDefs = MID.ImplicitDefs)
	for (unsigned i = 0; ImplicitDefs[i]; ++i)
	  HandlePhysRegDef(ImplicitDefs[i], MI);

      // Process all explicit defs...
      for (unsigned i = 0; i != NumOperandsToProcess; ++i) {
	MachineOperand &MO = MI->getOperand(i);
	if (MO.opIsDef() || MO.opIsDefAndUse()) {
	  if (MO.isVirtualRegister()) {
	    unsigned RegIdx = MO.getReg()-MRegisterInfo::FirstVirtualRegister;
	    VarInfo &VRInfo = getVarInfo(RegIdx);

	    assert(VRInfo.DefBlock == 0 && "Variable multiply defined!");
	    VRInfo.DefBlock = MBB;                           // Created here...
	    VRInfo.DefInst = MI;
	    VRInfo.Kills.push_back(std::make_pair(MBB, MI)); // Defaults to dead
	  } else if (MO.isPhysicalRegister() && MO.getReg() != 0) {
	    HandlePhysRegDef(MO.getReg(), MI);
	  }
	}
      }
    }

    // Handle any virtual assignments from PHI nodes which might be at the
    // bottom of this basic block.  We check all of our successor blocks to see
    // if they have PHI nodes, and if so, we simulate an assignment at the end
    // of the current block.
    for (succ_const_iterator SI = succ_begin(BB), E = succ_end(BB);
         SI != E; ++SI) {
      MachineBasicBlock *Succ = BBMap.find(*SI)->second.first;

      // PHI nodes are guaranteed to be at the top of the block...
      for (MachineBasicBlock::iterator I = Succ->begin(), E = Succ->end();
	   I != E && (*I)->getOpcode() == TargetInstrInfo::PHI; ++I) {
        MachineInstr *MI = *I;
	for (unsigned i = 1; ; i += 2)
	  if (MI->getOperand(i+1).getMachineBasicBlock() == MBB) {
	    MachineOperand &MO = MI->getOperand(i);
	    if (!MO.getVRegValueOrNull()) {
	      unsigned RegIdx = MO.getReg()-MRegisterInfo::FirstVirtualRegister;
	      VarInfo &VRInfo = getVarInfo(RegIdx);

	      // Only mark it alive only in the block we are representing...
	      MarkVirtRegAliveInBlock(VRInfo, BB);
	      break;   // Found the PHI entry for this block...
	    }
	  }
      }
    }

    // Loop over PhysRegInfo, killing any registers that are available at the
    // end of the basic block.  This also resets the PhysRegInfo map.
    for (unsigned i = 0, e = MRegisterInfo::FirstVirtualRegister; i != e; ++i)
      if (PhysRegInfo[i])
	HandlePhysRegDef(i, 0);
  }

  BBMap.clear();

  // Convert the information we have gathered into VirtRegInfo and transform it
  // into a form usable by RegistersKilled.
  //
  for (unsigned i = 0, e = VirtRegInfo.size(); i != e; ++i)
    for (unsigned j = 0, e = VirtRegInfo[i].Kills.size(); j != e; ++j) {
      if (VirtRegInfo[i].Kills[j].second == VirtRegInfo[i].DefInst)
	RegistersDead.insert(std::make_pair(VirtRegInfo[i].Kills[j].second,
		    i + MRegisterInfo::FirstVirtualRegister));

      else
	RegistersKilled.insert(std::make_pair(VirtRegInfo[i].Kills[j].second,
		    i + MRegisterInfo::FirstVirtualRegister));
    }

  return false;
}
<|endoftext|>