<commit_before>#include "chimera/render/LoadHeightMap.hpp"
#include <SDL2/SDL.h>

namespace Chimera {

LoadHeightMap::LoadHeightMap() : pImage(nullptr) { clean(); }

LoadHeightMap::~LoadHeightMap() { clean(); }

void LoadHeightMap::clean() {
    scale = glm::vec3(1.0f);
    if (pImage != nullptr) {
        SDL_FreeSurface(pImage);
        pImage = nullptr;
    }
}

uint32_t LoadHeightMap::getHeight(int w, int h) {
    unsigned w1 = w < 0 ? 0 : w > pImage->w ? pImage->w : w;
    unsigned h1 = h < 0 ? 0 : h > pImage->h ? pImage->h : h;
    return getpixel(w1, h1);
}

Uint32 LoadHeightMap::getpixel(const unsigned& w, const unsigned& h) {
    int bpp = pImage->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to retrieve */
    Uint8* p = (Uint8*)pImage->pixels + h * pImage->pitch + w * bpp;

    switch (bpp) {
        case 1:
            return *p;
            break;

        case 2:
            return *(Uint16*)p;
            break;

        case 3:
            if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
                return p[0] << 16 | p[1] << 8 | p[2];
            else
                return p[0] | p[1] << 8 | p[2] << 16;
            break;

        case 4:
            return *(Uint32*)p;
            break;

        default:
            return 0; /* shouldn't happen, but avoids warnings */
    }
}

void LoadHeightMap::defineScale(const glm::vec3& _size) {
    uint32_t min, max;
    min = max = getHeight(0, 0);
    for (int z = 0; z < pImage->h; z++) {
        for (int x = 0; x < pImage->w; x++) {
            uint32_t val = getHeight(x, z);

            if (val > max)
                max = val;
            if (val < min)
                min = val;
        }
    }

    scale.x = _size.x / (float)pImage->w;
    scale.y = _size.y / (float)(max - min);
    scale.z = _size.z / (float)pImage->h;
}

glm::vec3 LoadHeightMap::calcNormalHeight(int x, int z) {

    // [6][7][8] [x-1, y+1] [x,y+1] [x+1, y+1]
    // [3][4][5] [x-1, y]   [x,y]   [x+1, y]
    // [0][1][2] [x-1, y-1] [x, y-1][x+1, y-1]
    // Then,
    // float s[9];
    // s[0] = getHeight(x - 1, z - 1);
    // s[1] = getHeight(x, z - 1);
    // s[2] = getHeight(x + 1, z - 1);
    // s[3] = getHeight(x - 1, z);
    // s[4] = getHeight(x, z);
    // s[5] = getHeight(x + 1, z);
    // s[6] = getHeight(x - 1, z + 1);
    // s[7] = getHeight(x, z + 1);
    // s[8] = getHeight(x + 1, z + 1);
    // return glm::normalize(glm::vec3(-(s[2] - s[0] + 2 * (s[5] - s[3]) + s[8] - s[6]),   // x
    //                                 1.0f,                                               // y
    //                                 -(s[6] - s[0] + 2 * (s[7] - s[1]) + s[8] - s[2]))); // z

    return glm::normalize(glm::vec3((scale.y * getHeight(x - 1, z)) - (scale.y * getHeight(x + 1, z)),   // norx
                                    2.0f,                                                                // nory
                                    (scale.y * getHeight(x, z - 1)) - (scale.y * getHeight(x, z + 1)))); // norz
}

bool LoadHeightMap::getMesh(const std::string& _fileName, MeshData& _mesh, const glm::vec3& _size) {

    pImage = IMG_Load(_fileName.c_str());
    if (pImage == nullptr) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error opening file : %s", _fileName.c_str());
        return false;
    }

    float halfH = (float)pImage->h / 2.0f;
    float haldW = (float)pImage->w / 2.0f;

    float v = 1.0f / (pImage->h - 1);
    float u = 1.0f / (pImage->w - 1);

    defineScale(_size);

    for (int z = 0; z < pImage->h; z++) {
        for (int x = 0; x < pImage->w; x++) {

            glm::vec3 pos = glm::vec3(scale.x * ((float)x - haldW),  // posx
                                      scale.y * getHeight(x, z),     // posy
                                      scale.z * (halfH - (float)z)); // posz

            glm::vec3 nor = calcNormalHeight(x, z);

            float v1 = v * z;
            float u1 = u * x;

            _mesh.addVertex(pos);
            _mesh.addNormal(nor);
            _mesh.addUV(glm::vec2(u1, v1));
        }
    }

    int tot_h = pImage->h - 1;
    int tot_w = pImage->w - 1;

    for (int z = 0; z < tot_h; z++) {
        for (int x = 0; x < tot_w; x++) {
            // triangles point
            int pa = getIndex(x, z);
            int pb = getIndex(x + 1, z);
            int pc = getIndex(x + 1, z + 1);
            int pd = getIndex(x, z + 1);
            // Vertex T1
            _mesh.addVertexIndex(pa);
            _mesh.addVertexIndex(pb);
            _mesh.addVertexIndex(pc);
            // Vertex T2
            _mesh.addVertexIndex(pc);
            _mesh.addVertexIndex(pd);
            _mesh.addVertexIndex(pa);
            // normal T1
            _mesh.addNormalIndex(pa);
            _mesh.addNormalIndex(pb);
            _mesh.addNormalIndex(pc);
            // normal T2
            _mesh.addNormalIndex(pc);
            _mesh.addNormalIndex(pd);
            _mesh.addNormalIndex(pa);
            // UV T1
            _mesh.addUVIndex(pa);
            _mesh.addUVIndex(pb);
            _mesh.addUVIndex(pc);
            // UV T2
            _mesh.addUVIndex(pc);
            _mesh.addUVIndex(pd);
            _mesh.addUVIndex(pa);
        }
    }

    _mesh.debugDados(true);
    _mesh.setSingleIndex(true);

    return true;
}
} // namespace Chimera
<commit_msg>limpeza<commit_after>#include "chimera/render/LoadHeightMap.hpp"
#include <SDL2/SDL.h>

namespace Chimera {

LoadHeightMap::LoadHeightMap() : pImage(nullptr) { clean(); }

LoadHeightMap::~LoadHeightMap() { clean(); }

void LoadHeightMap::clean() {
    scale = glm::vec3(1.0f);
    if (pImage != nullptr) {
        SDL_FreeSurface(pImage);
        pImage = nullptr;
    }
}

uint32_t LoadHeightMap::getHeight(int w, int h) {
    unsigned w1 = w < 0 ? 0 : w > pImage->w ? pImage->w : w;
    unsigned h1 = h < 0 ? 0 : h > pImage->h ? pImage->h : h;
    return getpixel(w1, h1);
}

Uint32 LoadHeightMap::getpixel(const unsigned& w, const unsigned& h) {
    int bpp = pImage->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to retrieve */
    Uint8* p = (Uint8*)pImage->pixels + h * pImage->pitch + w * bpp;

    switch (bpp) {
        case 1:
            return *p;
            break;

        case 2:
            return *(Uint16*)p;
            break;

        case 3:
            if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
                return p[0] << 16 | p[1] << 8 | p[2];
            else
                return p[0] | p[1] << 8 | p[2] << 16;
            break;

        case 4:
            return *(Uint32*)p;
            break;

        default:
            return 0; /* shouldn't happen, but avoids warnings */
    }
}

void LoadHeightMap::defineScale(const glm::vec3& _size) {
    uint32_t min, max;
    min = max = getHeight(0, 0);
    for (int z = 0; z < pImage->h; z++) {
        for (int x = 0; x < pImage->w; x++) {
            uint32_t val = getHeight(x, z);

            if (val > max)
                max = val;
            if (val < min)
                min = val;
        }
    }

    scale.x = _size.x / (float)pImage->w;
    scale.y = _size.y / (float)(max - min);
    scale.z = _size.z / (float)pImage->h;
}

glm::vec3 LoadHeightMap::calcNormalHeight(int x, int z) {

    // [6][7][8] [x-1, y+1] [x,y+1] [x+1, y+1]
    // [3][4][5] [x-1, y]   [x,y]   [x+1, y]
    // [0][1][2] [x-1, y-1] [x, y-1][x+1, y-1]
    // Then,
    // float s[9];
    // s[0] = getHeight(x - 1, z - 1);
    // s[1] = getHeight(x, z - 1);
    // s[2] = getHeight(x + 1, z - 1);
    // s[3] = getHeight(x - 1, z);
    // s[4] = getHeight(x, z);
    // s[5] = getHeight(x + 1, z);
    // s[6] = getHeight(x - 1, z + 1);
    // s[7] = getHeight(x, z + 1);
    // s[8] = getHeight(x + 1, z + 1);
    // return glm::normalize(glm::vec3(-(s[2] - s[0] + 2 * (s[5] - s[3]) + s[8] - s[6]),   // x
    //                                 1.0f,                                               // y
    //                                 -(s[6] - s[0] + 2 * (s[7] - s[1]) + s[8] - s[2]))); // z

    return glm::normalize(glm::vec3((scale.y * getHeight(x - 1, z)) - (scale.y * getHeight(x + 1, z)),   // norx
                                    2.0f,                                                                // nory
                                    (scale.y * getHeight(x, z - 1)) - (scale.y * getHeight(x, z + 1)))); // norz
}

bool LoadHeightMap::getMesh(const std::string& _fileName, MeshData& _mesh, const glm::vec3& _size) {

    pImage = IMG_Load(_fileName.c_str());
    if (pImage == nullptr) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error opening file : %s", _fileName.c_str());
        return false;
    }

    float halfH = (float)pImage->h / 2.0f;
    float haldW = (float)pImage->w / 2.0f;

    float v = 1.0f / (pImage->h - 1);
    float u = 1.0f / (pImage->w - 1);

    defineScale(_size);

    for (int z = 0; z < pImage->h; z++) {
        for (int x = 0; x < pImage->w; x++) {

            _mesh.addVertex(glm::vec3(x - haldW, getHeight(x, z), halfH - z) * scale);
            _mesh.addNormal(calcNormalHeight(x, z));
            _mesh.addUV(glm::vec2(u * x, v * z));
        }
    }

    int tot_h = pImage->h - 1;
    int tot_w = pImage->w - 1;

    for (int z = 0; z < tot_h; z++) {
        for (int x = 0; x < tot_w; x++) {
            // triangles point
            int pa = getIndex(x, z);
            int pb = getIndex(x + 1, z);
            int pc = getIndex(x + 1, z + 1);
            int pd = getIndex(x, z + 1);
            // Vertex T1
            _mesh.addVertexIndex(pa);
            _mesh.addVertexIndex(pb);
            _mesh.addVertexIndex(pc);
            // Vertex T2
            _mesh.addVertexIndex(pc);
            _mesh.addVertexIndex(pd);
            _mesh.addVertexIndex(pa);
            // normal T1
            _mesh.addNormalIndex(pa);
            _mesh.addNormalIndex(pb);
            _mesh.addNormalIndex(pc);
            // normal T2
            _mesh.addNormalIndex(pc);
            _mesh.addNormalIndex(pd);
            _mesh.addNormalIndex(pa);
            // UV T1
            _mesh.addUVIndex(pa);
            _mesh.addUVIndex(pb);
            _mesh.addUVIndex(pc);
            // UV T2
            _mesh.addUVIndex(pc);
            _mesh.addUVIndex(pd);
            _mesh.addUVIndex(pa);
        }
    }

    _mesh.debugDados(true);
    _mesh.setSingleIndex(true);

    return true;
}
} // namespace Chimera
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/common_param_traits.h"

#include "chrome/common/chrome_constants.h"
#include "gfx/rect.h"
#include "googleurl/src/gurl.h"
#ifndef EXCLUDE_SKIA_DEPENDENCIES
#include "third_party/skia/include/core/SkBitmap.h"
#endif
#include "webkit/glue/dom_operations.h"

namespace IPC {

#ifndef EXCLUDE_SKIA_DEPENDENCIES

namespace {

struct SkBitmap_Data {
  // The configuration for the bitmap (bits per pixel, etc).
  SkBitmap::Config fConfig;

  // The width of the bitmap in pixels.
  uint32 fWidth;

  // The height of the bitmap in pixels.
  uint32 fHeight;

  void InitSkBitmapDataForTransfer(const SkBitmap& bitmap) {
    fConfig = bitmap.config();
    fWidth = bitmap.width();
    fHeight = bitmap.height();
  }

  // Returns whether |bitmap| successfully initialized.
  bool InitSkBitmapFromData(SkBitmap* bitmap, const char* pixels,
                            size_t total_pixels) const {
    if (total_pixels) {
      bitmap->setConfig(fConfig, fWidth, fHeight, 0);
      if (!bitmap->allocPixels())
        return false;
      if (total_pixels != bitmap->getSize())
        return false;
      memcpy(bitmap->getPixels(), pixels, total_pixels);
    }
    return true;
  }
};

}  // namespace

void ParamTraits<SkBitmap>::Write(Message* m, const SkBitmap& p) {
  size_t fixed_size = sizeof(SkBitmap_Data);
  SkBitmap_Data bmp_data;
  bmp_data.InitSkBitmapDataForTransfer(p);
  m->WriteData(reinterpret_cast<const char*>(&bmp_data),
               static_cast<int>(fixed_size));
  size_t pixel_size = p.getSize();
  SkAutoLockPixels p_lock(p);
  m->WriteData(reinterpret_cast<const char*>(p.getPixels()),
               static_cast<int>(pixel_size));
}

bool ParamTraits<SkBitmap>::Read(const Message* m, void** iter, SkBitmap* r) {
  const char* fixed_data;
  int fixed_data_size = 0;
  if (!m->ReadData(iter, &fixed_data, &fixed_data_size) ||
     (fixed_data_size <= 0)) {
    NOTREACHED();
    return false;
  }
  if (fixed_data_size != sizeof(SkBitmap_Data))
    return false;  // Message is malformed.

  const char* variable_data;
  int variable_data_size = 0;
  if (!m->ReadData(iter, &variable_data, &variable_data_size) ||
     (variable_data_size < 0)) {
    NOTREACHED();
    return false;
  }
  const SkBitmap_Data* bmp_data =
      reinterpret_cast<const SkBitmap_Data*>(fixed_data);
  return bmp_data->InitSkBitmapFromData(r, variable_data, variable_data_size);
}

void ParamTraits<SkBitmap>::Log(const SkBitmap& p, std::wstring* l) {
  l->append(StringPrintf(L"<SkBitmap>"));
}

#endif  // EXCLUDE_SKIA_DEPENDENCIES

void ParamTraits<GURL>::Write(Message* m, const GURL& p) {
  m->WriteString(p.possibly_invalid_spec());
  // TODO(brettw) bug 684583: Add encoding for query params.
}

bool ParamTraits<GURL>::Read(const Message* m, void** iter, GURL* p) {
  std::string s;
  if (!m->ReadString(iter, &s) || s.length() > chrome::kMaxURLChars) {
    *p = GURL();
    return false;
  }
  *p = GURL(s);
  return true;
}

void ParamTraits<GURL>::Log(const GURL& p, std::wstring* l) {
  l->append(UTF8ToWide(p.spec()));
}

void ParamTraits<gfx::Point>::Write(Message* m, const gfx::Point& p) {
  m->WriteInt(p.x());
  m->WriteInt(p.y());
}

bool ParamTraits<gfx::Point>::Read(const Message* m, void** iter,
                                   gfx::Point* r) {
  int x, y;
  if (!m->ReadInt(iter, &x) ||
      !m->ReadInt(iter, &y))
    return false;
  r->set_x(x);
  r->set_y(y);
  return true;
}

void ParamTraits<gfx::Point>::Log(const gfx::Point& p, std::wstring* l) {
  l->append(StringPrintf(L"(%d, %d)", p.x(), p.y()));
}

void ParamTraits<gfx::Rect>::Write(Message* m, const gfx::Rect& p) {
  m->WriteInt(p.x());
  m->WriteInt(p.y());
  m->WriteInt(p.width());
  m->WriteInt(p.height());
}

bool ParamTraits<gfx::Rect>::Read(const Message* m, void** iter, gfx::Rect* r) {
  int x, y, w, h;
  if (!m->ReadInt(iter, &x) ||
      !m->ReadInt(iter, &y) ||
      !m->ReadInt(iter, &w) ||
      !m->ReadInt(iter, &h))
    return false;
  if (x < 0 || y < 0 || x >= (INT_MAX - w) || y >= (INT_MAX - h) ||
      w < 0 || h < 0 || h >= ((INT_MAX / 16) / (w ? w : 1)))
    return false;
  r->set_x(x);
  r->set_y(y);
  r->set_width(w);
  r->set_height(h);
  return true;
}

void ParamTraits<gfx::Rect>::Log(const gfx::Rect& p, std::wstring* l) {
  l->append(StringPrintf(L"(%d, %d, %d, %d)", p.x(), p.y(),
                         p.width(), p.height()));
}

void ParamTraits<gfx::Size>::Write(Message* m, const gfx::Size& p) {
  m->WriteInt(p.width());
  m->WriteInt(p.height());
}

bool ParamTraits<gfx::Size>::Read(const Message* m, void** iter, gfx::Size* r) {
  int w, h;
  if (!m->ReadInt(iter, &w) ||
      !m->ReadInt(iter, &h))
    return false;
  if (w < 0 || h < 0 || h >= ((INT_MAX / 16) / (w ? w : 1)))
    return false;
  r->set_width(w);
  r->set_height(h);
  return true;
}

void ParamTraits<gfx::Size>::Log(const gfx::Size& p, std::wstring* l) {
  l->append(StringPrintf(L"(%d, %d)", p.width(), p.height()));
}

void ParamTraits<ContentSettings>::Write(
    Message* m, const ContentSettings& settings) {
  for (size_t i = 0; i < arraysize(settings.settings); ++i)
    WriteParam(m, settings.settings[i]);
}

bool ParamTraits<ContentSettings>::Read(
    const Message* m, void** iter, ContentSettings* r) {
  for (size_t i = 0; i < arraysize(r->settings); ++i) {
    if (!ReadParam(m, iter, &r->settings[i]))
      return false;
  }
  return true;
}

void ParamTraits<ContentSettings>::Log(
    const ContentSettings& p, std::wstring* l) {
  l->append(StringPrintf(L"<ContentSettings>"));
}

void ParamTraits<webkit_glue::WebApplicationInfo>::Write(
    Message* m, const webkit_glue::WebApplicationInfo& p) {
  WriteParam(m, p.title);
  WriteParam(m, p.description);
  WriteParam(m, p.app_url);
  WriteParam(m, p.icons.size());
  for (size_t i = 0; i < p.icons.size(); ++i) {
    WriteParam(m, p.icons[i].url);
    WriteParam(m, p.icons[i].width);
    WriteParam(m, p.icons[i].height);
  }
}

bool ParamTraits<webkit_glue::WebApplicationInfo>::Read(
    const Message* m, void** iter, webkit_glue::WebApplicationInfo* r) {
  size_t icon_count;
  bool result =
    ReadParam(m, iter, &r->title) &&
    ReadParam(m, iter, &r->description) &&
    ReadParam(m, iter, &r->app_url) &&
    ReadParam(m, iter, &icon_count);
  if (!result)
    return false;
  for (size_t i = 0; i < icon_count; ++i) {
    param_type::IconInfo icon_info;
    result =
        ReadParam(m, iter, &icon_info.url) &&
        ReadParam(m, iter, &icon_info.width) &&
        ReadParam(m, iter, &icon_info.height);
    if (!result)
      return false;
    r->icons.push_back(icon_info);
  }
  return true;
}

void ParamTraits<webkit_glue::WebApplicationInfo>::Log(
    const webkit_glue::WebApplicationInfo& p, std::wstring* l) {
  l->append(L"<WebApplicationInfo>");
}

void ParamTraits<Geoposition::ErrorCode>::Write(
    Message* m, const Geoposition::ErrorCode& p) {
  int error_code = p;
  WriteParam(m, error_code);
}

bool ParamTraits<Geoposition::ErrorCode>::Read(
      const Message* m, void** iter, Geoposition::ErrorCode* p) {
  int error_code_param = 0;
  bool ret = ReadParam(m, iter, &error_code_param);
  *p = static_cast<Geoposition::ErrorCode>(error_code_param);
  return ret;
}

void ParamTraits<Geoposition::ErrorCode>::Log(
    const Geoposition::ErrorCode& p, std::wstring* l) {
  int error_code = p;
  l->append(StringPrintf(L"<Geoposition::ErrorCode>%d", error_code));
}

void ParamTraits<Geoposition>::Write(Message* m, const Geoposition& p) {
  WriteParam(m, p.latitude);
  WriteParam(m, p.longitude);
  WriteParam(m, p.accuracy);
  WriteParam(m, p.altitude);
  WriteParam(m, p.altitude_accuracy);
  WriteParam(m, p.speed);
  WriteParam(m, p.heading);
  WriteParam(m, p.timestamp);
  WriteParam(m, p.error_code);
  WriteParam(m, p.error_message);
}

bool ParamTraits<Geoposition>::Read(
      const Message* m, void** iter, Geoposition* p) {
  bool ret = ReadParam(m, iter, &p->latitude);
  ret = ret && ReadParam(m, iter, &p->longitude);
  ret = ret && ReadParam(m, iter, &p->accuracy);
  ret = ret && ReadParam(m, iter, &p->altitude);
  ret = ret && ReadParam(m, iter, &p->altitude_accuracy);
  ret = ret && ReadParam(m, iter, &p->speed);
  ret = ret && ReadParam(m, iter, &p->heading);
  ret = ret && ReadParam(m, iter, &p->timestamp);
  ret = ret && ReadParam(m, iter, &p->error_code);
  ret = ret && ReadParam(m, iter, &p->error_message);
  return ret;
}

void ParamTraits<Geoposition>::Log(const Geoposition& p, std::wstring* l) {
  l->append(
      StringPrintf(
          L"<Geoposition>"
          L"%.6f %.6f %.6f %.6f "
          L"%.6f %.6f %.6f ",
          p.latitude, p.longitude, p.accuracy, p.altitude,
          p.altitude_accuracy, p.speed, p.heading));
  LogParam(p.timestamp, l);
  l->append(L" ");
  l->append(p.error_message);
  LogParam(p.error_code, l);
}

}  // namespace IPC
<commit_msg>Revert 45797 - Apply a sanity limit to objects with width & height.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/common_param_traits.h"

#include "chrome/common/chrome_constants.h"
#include "gfx/rect.h"
#include "googleurl/src/gurl.h"
#ifndef EXCLUDE_SKIA_DEPENDENCIES
#include "third_party/skia/include/core/SkBitmap.h"
#endif
#include "webkit/glue/dom_operations.h"

namespace IPC {

#ifndef EXCLUDE_SKIA_DEPENDENCIES

namespace {

struct SkBitmap_Data {
  // The configuration for the bitmap (bits per pixel, etc).
  SkBitmap::Config fConfig;

  // The width of the bitmap in pixels.
  uint32 fWidth;

  // The height of the bitmap in pixels.
  uint32 fHeight;

  void InitSkBitmapDataForTransfer(const SkBitmap& bitmap) {
    fConfig = bitmap.config();
    fWidth = bitmap.width();
    fHeight = bitmap.height();
  }

  // Returns whether |bitmap| successfully initialized.
  bool InitSkBitmapFromData(SkBitmap* bitmap, const char* pixels,
                            size_t total_pixels) const {
    if (total_pixels) {
      bitmap->setConfig(fConfig, fWidth, fHeight, 0);
      if (!bitmap->allocPixels())
        return false;
      if (total_pixels != bitmap->getSize())
        return false;
      memcpy(bitmap->getPixels(), pixels, total_pixels);
    }
    return true;
  }
};

}  // namespace

void ParamTraits<SkBitmap>::Write(Message* m, const SkBitmap& p) {
  size_t fixed_size = sizeof(SkBitmap_Data);
  SkBitmap_Data bmp_data;
  bmp_data.InitSkBitmapDataForTransfer(p);
  m->WriteData(reinterpret_cast<const char*>(&bmp_data),
               static_cast<int>(fixed_size));
  size_t pixel_size = p.getSize();
  SkAutoLockPixels p_lock(p);
  m->WriteData(reinterpret_cast<const char*>(p.getPixels()),
               static_cast<int>(pixel_size));
}

bool ParamTraits<SkBitmap>::Read(const Message* m, void** iter, SkBitmap* r) {
  const char* fixed_data;
  int fixed_data_size = 0;
  if (!m->ReadData(iter, &fixed_data, &fixed_data_size) ||
     (fixed_data_size <= 0)) {
    NOTREACHED();
    return false;
  }
  if (fixed_data_size != sizeof(SkBitmap_Data))
    return false;  // Message is malformed.

  const char* variable_data;
  int variable_data_size = 0;
  if (!m->ReadData(iter, &variable_data, &variable_data_size) ||
     (variable_data_size < 0)) {
    NOTREACHED();
    return false;
  }
  const SkBitmap_Data* bmp_data =
      reinterpret_cast<const SkBitmap_Data*>(fixed_data);
  return bmp_data->InitSkBitmapFromData(r, variable_data, variable_data_size);
}

void ParamTraits<SkBitmap>::Log(const SkBitmap& p, std::wstring* l) {
  l->append(StringPrintf(L"<SkBitmap>"));
}

#endif  // EXCLUDE_SKIA_DEPENDENCIES

void ParamTraits<GURL>::Write(Message* m, const GURL& p) {
  m->WriteString(p.possibly_invalid_spec());
  // TODO(brettw) bug 684583: Add encoding for query params.
}

bool ParamTraits<GURL>::Read(const Message* m, void** iter, GURL* p) {
  std::string s;
  if (!m->ReadString(iter, &s) || s.length() > chrome::kMaxURLChars) {
    *p = GURL();
    return false;
  }
  *p = GURL(s);
  return true;
}

void ParamTraits<GURL>::Log(const GURL& p, std::wstring* l) {
  l->append(UTF8ToWide(p.spec()));
}

void ParamTraits<gfx::Point>::Write(Message* m, const gfx::Point& p) {
  m->WriteInt(p.x());
  m->WriteInt(p.y());
}

bool ParamTraits<gfx::Point>::Read(const Message* m, void** iter,
                                   gfx::Point* r) {
  int x, y;
  if (!m->ReadInt(iter, &x) ||
      !m->ReadInt(iter, &y))
    return false;
  r->set_x(x);
  r->set_y(y);
  return true;
}

void ParamTraits<gfx::Point>::Log(const gfx::Point& p, std::wstring* l) {
  l->append(StringPrintf(L"(%d, %d)", p.x(), p.y()));
}

void ParamTraits<gfx::Rect>::Write(Message* m, const gfx::Rect& p) {
  m->WriteInt(p.x());
  m->WriteInt(p.y());
  m->WriteInt(p.width());
  m->WriteInt(p.height());
}

bool ParamTraits<gfx::Rect>::Read(const Message* m, void** iter, gfx::Rect* r) {
  int x, y, w, h;
  if (!m->ReadInt(iter, &x) ||
      !m->ReadInt(iter, &y) ||
      !m->ReadInt(iter, &w) ||
      !m->ReadInt(iter, &h))
    return false;
  r->set_x(x);
  r->set_y(y);
  r->set_width(w);
  r->set_height(h);
  return true;
}

void ParamTraits<gfx::Rect>::Log(const gfx::Rect& p, std::wstring* l) {
  l->append(StringPrintf(L"(%d, %d, %d, %d)", p.x(), p.y(),
                         p.width(), p.height()));
}

void ParamTraits<gfx::Size>::Write(Message* m, const gfx::Size& p) {
  m->WriteInt(p.width());
  m->WriteInt(p.height());
}

bool ParamTraits<gfx::Size>::Read(const Message* m, void** iter, gfx::Size* r) {
  int w, h;
  if (!m->ReadInt(iter, &w) ||
      !m->ReadInt(iter, &h))
    return false;
  r->set_width(w);
  r->set_height(h);
  return true;
}

void ParamTraits<gfx::Size>::Log(const gfx::Size& p, std::wstring* l) {
  l->append(StringPrintf(L"(%d, %d)", p.width(), p.height()));
}

void ParamTraits<ContentSettings>::Write(
    Message* m, const ContentSettings& settings) {
  for (size_t i = 0; i < arraysize(settings.settings); ++i)
    WriteParam(m, settings.settings[i]);
}

bool ParamTraits<ContentSettings>::Read(
    const Message* m, void** iter, ContentSettings* r) {
  for (size_t i = 0; i < arraysize(r->settings); ++i) {
    if (!ReadParam(m, iter, &r->settings[i]))
      return false;
  }
  return true;
}

void ParamTraits<ContentSettings>::Log(
    const ContentSettings& p, std::wstring* l) {
  l->append(StringPrintf(L"<ContentSettings>"));
}

void ParamTraits<webkit_glue::WebApplicationInfo>::Write(
    Message* m, const webkit_glue::WebApplicationInfo& p) {
  WriteParam(m, p.title);
  WriteParam(m, p.description);
  WriteParam(m, p.app_url);
  WriteParam(m, p.icons.size());
  for (size_t i = 0; i < p.icons.size(); ++i) {
    WriteParam(m, p.icons[i].url);
    WriteParam(m, p.icons[i].width);
    WriteParam(m, p.icons[i].height);
  }
}

bool ParamTraits<webkit_glue::WebApplicationInfo>::Read(
    const Message* m, void** iter, webkit_glue::WebApplicationInfo* r) {
  size_t icon_count;
  bool result =
    ReadParam(m, iter, &r->title) &&
    ReadParam(m, iter, &r->description) &&
    ReadParam(m, iter, &r->app_url) &&
    ReadParam(m, iter, &icon_count);
  if (!result)
    return false;
  for (size_t i = 0; i < icon_count; ++i) {
    param_type::IconInfo icon_info;
    result =
        ReadParam(m, iter, &icon_info.url) &&
        ReadParam(m, iter, &icon_info.width) &&
        ReadParam(m, iter, &icon_info.height);
    if (!result)
      return false;
    r->icons.push_back(icon_info);
  }
  return true;
}

void ParamTraits<webkit_glue::WebApplicationInfo>::Log(
    const webkit_glue::WebApplicationInfo& p, std::wstring* l) {
  l->append(L"<WebApplicationInfo>");
}

void ParamTraits<Geoposition::ErrorCode>::Write(
    Message* m, const Geoposition::ErrorCode& p) {
  int error_code = p;
  WriteParam(m, error_code);
}

bool ParamTraits<Geoposition::ErrorCode>::Read(
      const Message* m, void** iter, Geoposition::ErrorCode* p) {
  int error_code_param = 0;
  bool ret = ReadParam(m, iter, &error_code_param);
  *p = static_cast<Geoposition::ErrorCode>(error_code_param);
  return ret;
}

void ParamTraits<Geoposition::ErrorCode>::Log(
    const Geoposition::ErrorCode& p, std::wstring* l) {
  int error_code = p;
  l->append(StringPrintf(L"<Geoposition::ErrorCode>%d", error_code));
}

void ParamTraits<Geoposition>::Write(Message* m, const Geoposition& p) {
  WriteParam(m, p.latitude);
  WriteParam(m, p.longitude);
  WriteParam(m, p.accuracy);
  WriteParam(m, p.altitude);
  WriteParam(m, p.altitude_accuracy);
  WriteParam(m, p.speed);
  WriteParam(m, p.heading);
  WriteParam(m, p.timestamp);
  WriteParam(m, p.error_code);
  WriteParam(m, p.error_message);
}

bool ParamTraits<Geoposition>::Read(
      const Message* m, void** iter, Geoposition* p) {
  bool ret = ReadParam(m, iter, &p->latitude);
  ret = ret && ReadParam(m, iter, &p->longitude);
  ret = ret && ReadParam(m, iter, &p->accuracy);
  ret = ret && ReadParam(m, iter, &p->altitude);
  ret = ret && ReadParam(m, iter, &p->altitude_accuracy);
  ret = ret && ReadParam(m, iter, &p->speed);
  ret = ret && ReadParam(m, iter, &p->heading);
  ret = ret && ReadParam(m, iter, &p->timestamp);
  ret = ret && ReadParam(m, iter, &p->error_code);
  ret = ret && ReadParam(m, iter, &p->error_message);
  return ret;
}

void ParamTraits<Geoposition>::Log(const Geoposition& p, std::wstring* l) {
  l->append(
      StringPrintf(
          L"<Geoposition>"
          L"%.6f %.6f %.6f %.6f "
          L"%.6f %.6f %.6f ",
          p.latitude, p.longitude, p.accuracy, p.altitude,
          p.altitude_accuracy, p.speed, p.heading));
  LogParam(p.timestamp, l);
  l->append(L" ");
  l->append(p.error_message);
  LogParam(p.error_code, l);
}

}  // namespace IPC
<|endoftext|>


<commit_before>/*
   This file is part of KDE Kontact.

   Copyright (C) 2003 Sven Lppken <sven@kde.org>

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

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include <qframe.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qtimer.h>

#include <dcopclient.h>
#include <kaction.h>
#include <kapplication.h>
#include <kdcopservicestarter.h>
#include <kdebug.h>
#include <kdialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kparts/componentfactory.h>
#include <kservice.h>
#include <ktrader.h>

#include <infoextension.h>
#include "plugin.h"
#include <sidebarextension.h>

#include "summaryview_part.h"

namespace Kontact
{
  class MainWindow;
}

SummaryViewPart::SummaryViewPart( Kontact::Core *core, const char *widgetName,
                                  QObject *parent, const char *name )
  : KParts::ReadOnlyPart( parent, name ),
    mCore( core )
{
  setInstance( new KInstance( "summaryviewpart" ) ); // ## memleak

  mFrame = new QFrame( core, widgetName );
  mFrame->setPaletteBackgroundColor( QColor( 240, 240, 240 ) );
  setWidget( mFrame );

  mLayout = new QGridLayout( mFrame, 4, 3, KDialog::marginHint(),
                             KDialog::spacingHint() );

  QFrame *frame = new QFrame( mFrame );
  frame->setFrameStyle( QFrame::VLine | QFrame::Sunken );
  mLayout->addMultiCellWidget( frame, 0, 3, 1, 1 );

  frame = new QFrame( mFrame );
  frame->setFrameStyle( QFrame::HLine | QFrame::Sunken );
  mLayout->addWidget( frame, 1, 0 );

  getWidgets();

  KParts::InfoExtension *info = new KParts::InfoExtension( this, "Summary" );
  connect( this, SIGNAL( textChanged( const QString& ) ),
           info, SIGNAL( textChanged( const QString& ) ) );

  QTimer::singleShot( 0, this, SLOT( slotTextChanged() ) );
}

SummaryViewPart::~SummaryViewPart()
{
  kapp->dcopClient()->setNotifications( false );
}

bool SummaryViewPart::openFile()
{
  kdDebug(5006) << "SummaryViewPart:openFile()" << endl;
  return true;
}

void SummaryViewPart::getWidgets()
{
  QPtrList<Kontact::Plugin> plugins = mCore->pluginList();
  Kontact::Plugin *plugin;
  for ( plugin = plugins.first(); plugin; plugin = plugins.next() ) {
    QWidget *wdg = plugin->createSummaryWidget( mFrame );
    kdDebug(5006) <<  "identifier=" << plugin->identifier() << endl;
    if ( plugin->identifier() == "weather" ) {
      mLayout->addWidget( wdg, 0, 0 );
    } else if ( plugin->identifier() == "mails" ) {
      mLayout->addWidget( wdg, 0, 2 );
    } else if ( plugin->identifier()  == "newsticker" ) {
      mLayout->addMultiCellWidget( wdg, 2, 3, 0, 0 );
    } else if ( plugin->identifier() == "notes" ) {
      mLayout->addMultiCellWidget( wdg, 1, 2, 2, 2 );
    } else if ( plugin->identifier() == "contacts" ) {
      mLayout->addWidget( wdg, 3, 2 );
    }
  }
}

void SummaryViewPart::slotTextChanged()
{
  emit textChanged( i18n( "What's next?" ) );
}

#include "summaryview_part.moc"
<commit_msg>Improved layout (tm) and tokoe asked me to remove the debug output completely...<commit_after>/*
   This file is part of KDE Kontact.

   Copyright (C) 2003 Sven Lppken <sven@kde.org>

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

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include <qframe.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qtimer.h>

#include <dcopclient.h>
#include <kaction.h>
#include <kapplication.h>
#include <kdcopservicestarter.h>
#include <kdebug.h>
#include <kdialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kparts/componentfactory.h>
#include <kservice.h>
#include <ktrader.h>

#include <infoextension.h>
#include "plugin.h"
#include <sidebarextension.h>

#include "summaryview_part.h"

namespace Kontact
{
  class MainWindow;
}

SummaryViewPart::SummaryViewPart( Kontact::Core *core, const char *widgetName,
                                  QObject *parent, const char *name )
  : KParts::ReadOnlyPart( parent, name ),
    mCore( core )
{
  setInstance( new KInstance( "summaryviewpart" ) ); // ## memleak

  mFrame = new QFrame( core, widgetName );
  mFrame->setPaletteBackgroundColor( QColor( 240, 240, 240 ) );
  setWidget( mFrame );

  mLayout = new QGridLayout( mFrame, 6, 3, KDialog::marginHint(),
                             KDialog::spacingHint() );

  QFrame *frame = new QFrame( mFrame );
  frame->setFrameStyle( QFrame::VLine | QFrame::Sunken );
  mLayout->addMultiCellWidget( frame, 0, 5, 1, 1 );

  frame = new QFrame( mFrame );
  frame->setFrameStyle( QFrame::HLine | QFrame::Sunken );
  mLayout->addWidget( frame, 1, 0 );

  frame = new QFrame( mFrame );
  frame->setFrameStyle( QFrame::HLine | QFrame::Sunken );
  mLayout->addWidget( frame, 1, 2 );

  frame = new QFrame( mFrame );
  frame->setFrameStyle( QFrame::HLine | QFrame::Sunken );
  mLayout->addWidget( frame, 4, 2 );

  getWidgets();

  KParts::InfoExtension *info = new KParts::InfoExtension( this, "Summary" );
  connect( this, SIGNAL( textChanged( const QString& ) ),
           info, SIGNAL( textChanged( const QString& ) ) );

  QTimer::singleShot( 0, this, SLOT( slotTextChanged() ) );
}

SummaryViewPart::~SummaryViewPart()
{
  kapp->dcopClient()->setNotifications( false );
}

bool SummaryViewPart::openFile()
{
  kdDebug(5006) << "SummaryViewPart:openFile()" << endl;
  return true;
}

void SummaryViewPart::getWidgets()
{
  QPtrList<Kontact::Plugin> plugins = mCore->pluginList();
  Kontact::Plugin *plugin;
  for ( plugin = plugins.first(); plugin; plugin = plugins.next() ) {
    QWidget *wdg = plugin->createSummaryWidget( mFrame );
    if ( plugin->identifier() == "weather" ) {
      mLayout->addWidget( wdg, 0, 0 );
    } else if ( plugin->identifier() == "mails" ) {
      mLayout->addWidget( wdg, 0, 2 );
    } else if ( plugin->identifier()  == "newsticker" ) {
      mLayout->addMultiCellWidget( wdg, 2, 3, 0, 0 );
    } else if ( plugin->identifier() == "notes" ) {
      mLayout->addMultiCellWidget( wdg, 2, 3, 2, 2 );
    } else if ( plugin->identifier() == "contacts" ) {
      mLayout->addWidget( wdg, 5, 2 );
    }
  }
}

void SummaryViewPart::slotTextChanged()
{
  emit textChanged( i18n( "What's next?" ) );
}

#include "summaryview_part.moc"
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/dom_storage/dom_storage_database.h"

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/scoped_temp_dir.h"
#include "base/utf_string_conversions.h"
#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace dom_storage {

void CreateV1Table(sql::Connection* db) {
  ASSERT_TRUE(db->is_open());
  ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
  ASSERT_TRUE(db->Execute(
      "CREATE TABLE ItemTable ("
      "key TEXT UNIQUE ON CONFLICT REPLACE, "
      "value TEXT NOT NULL ON CONFLICT FAIL)"));
}

void CreateV2Table(sql::Connection* db) {
  ASSERT_TRUE(db->is_open());
  ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
  ASSERT_TRUE(db->Execute(
      "CREATE TABLE ItemTable ("
      "key TEXT UNIQUE ON CONFLICT REPLACE, "
      "value BLOB NOT NULL ON CONFLICT FAIL)"));
}

void CreateInvalidKeyColumnTable(sql::Connection* db) {
  // Create a table with the key type as FLOAT - this is "invalid"
  // as far as the DOM Storage db is concerned.
  ASSERT_TRUE(db->is_open());
  ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
  ASSERT_TRUE(db->Execute(
      "CREATE TABLE IF NOT EXISTS ItemTable ("
      "key FLOAT UNIQUE ON CONFLICT REPLACE, "
      "value BLOB NOT NULL ON CONFLICT FAIL)"));
}
void CreateInvalidValueColumnTable(sql::Connection* db) {
  // Create a table with the value type as FLOAT - this is "invalid"
  // as far as the DOM Storage db is concerned.
  ASSERT_TRUE(db->is_open());
  ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
  ASSERT_TRUE(db->Execute(
      "CREATE TABLE IF NOT EXISTS ItemTable ("
      "key TEXT UNIQUE ON CONFLICT REPLACE, "
      "value FLOAT NOT NULL ON CONFLICT FAIL)"));
}

void InsertDataV1(sql::Connection* db,
                  const string16& key,
                  const string16& value) {
  sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE,
      "INSERT INTO ItemTable VALUES (?,?)"));
  statement.BindString16(0, key);
  statement.BindString16(1, value);
  ASSERT_TRUE(statement.is_valid());
  statement.Run();
}

void CheckValuesMatch(DomStorageDatabase* db,
                      const ValuesMap& expected) {
  ValuesMap values_read;
  db->ReadAllValues(&values_read);
  EXPECT_EQ(expected.size(), values_read.size());

  ValuesMap::const_iterator it = values_read.begin();
  for (; it != values_read.end(); ++it) {
    string16 key = it->first;
    NullableString16 value = it->second;
    NullableString16 expected_value = expected.find(key)->second;
    EXPECT_EQ(expected_value.string(), value.string());
    EXPECT_EQ(expected_value.is_null(), value.is_null());
  }
}

void CreateMapWithValues(ValuesMap* values) {
  string16 kCannedKeys[] = {
      ASCIIToUTF16("test"),
      ASCIIToUTF16("company"),
      ASCIIToUTF16("date"),
      ASCIIToUTF16("empty")
  };
  NullableString16 kCannedValues[] = {
      NullableString16(ASCIIToUTF16("123"), false),
      NullableString16(ASCIIToUTF16("Google"), false),
      NullableString16(ASCIIToUTF16("18-01-2012"), false),
      NullableString16(ASCIIToUTF16(""), false)
  };
  for (unsigned i = 0; i < sizeof(kCannedKeys) / sizeof(kCannedKeys[0]); i++)
    (*values)[kCannedKeys[i]] = kCannedValues[i];
}

TEST(DomStorageDatabaseTest, SimpleOpenAndClose) {
  DomStorageDatabase db;
  EXPECT_FALSE(db.IsOpen());
  ASSERT_TRUE(db.LazyOpen(true));
  EXPECT_TRUE(db.IsOpen());
  EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());
  db.Close();
  EXPECT_FALSE(db.IsOpen());
}

TEST(DomStorageDatabaseTest, CloseEmptyDatabaseDeletesFile) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");
  ValuesMap storage;
  CreateMapWithValues(&storage);

  // First test the case that explicitly clearing the database will
  // trigger its deletion from disk.
  {
    DomStorageDatabase db(file_name);
    EXPECT_EQ(file_name, db.file_path());
    ASSERT_TRUE(db.CommitChanges(false, storage));
  }
  EXPECT_TRUE(file_util::PathExists(file_name));

  {
    // Check that reading an existing db with data in it
    // keeps the DB on disk on close.
    DomStorageDatabase db(file_name);
    ValuesMap values;
    db.ReadAllValues(&values);
    EXPECT_EQ(storage.size(), values.size());
  }

  EXPECT_TRUE(file_util::PathExists(file_name));
  storage.clear();

  {
    DomStorageDatabase db(file_name);
    ASSERT_TRUE(db.CommitChanges(true, storage));
  }
  EXPECT_FALSE(file_util::PathExists(file_name));

  // Now ensure that a series of updates and removals whose net effect
  // is an empty database also triggers deletion.
  CreateMapWithValues(&storage);
  {
    DomStorageDatabase db(file_name);
    ASSERT_TRUE(db.CommitChanges(false, storage));
  }

  EXPECT_TRUE(file_util::PathExists(file_name));

  {
    DomStorageDatabase db(file_name);
    ASSERT_TRUE(db.CommitChanges(false, storage));
    ValuesMap::iterator it = storage.begin();
    for (; it != storage.end(); ++it)
      it->second = NullableString16(true);
    ASSERT_TRUE(db.CommitChanges(false, storage));
  }
  EXPECT_FALSE(file_util::PathExists(file_name));
}

TEST(DomStorageDatabaseTest, TestLazyOpenIsLazy) {
  // This test needs to operate with a file on disk to ensure that we will
  // open a file that already exists when only invoking ReadAllValues.
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");

  DomStorageDatabase db(file_name);
  EXPECT_FALSE(db.IsOpen());
  ValuesMap values;
  db.ReadAllValues(&values);
  // Reading an empty db should not open the database.
  EXPECT_FALSE(db.IsOpen());

  values[ASCIIToUTF16("key")] = NullableString16(ASCIIToUTF16("value"), false);
  db.CommitChanges(false, values);
  // Writing content should open the database.
  EXPECT_TRUE(db.IsOpen());

  db.Close();
  ASSERT_FALSE(db.IsOpen());

  // Reading from an existing database should open the database.
  CheckValuesMatch(&db, values);
  EXPECT_TRUE(db.IsOpen());
}

TEST(DomStorageDatabaseTest, TestDetectSchemaVersion) {
  DomStorageDatabase db;
  db.db_.reset(new sql::Connection());
  ASSERT_TRUE(db.db_->OpenInMemory());

  CreateInvalidValueColumnTable(db.db_.get());
  EXPECT_EQ(DomStorageDatabase::INVALID, db.DetectSchemaVersion());

  CreateInvalidKeyColumnTable(db.db_.get());
  EXPECT_EQ(DomStorageDatabase::INVALID, db.DetectSchemaVersion());

  CreateV1Table(db.db_.get());
  EXPECT_EQ(DomStorageDatabase::V1, db.DetectSchemaVersion());

  CreateV2Table(db.db_.get());
  EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());
}

TEST(DomStorageDatabaseTest, TestLazyOpenUpgradesDatabase) {
  // This test needs to operate with a file on disk so that we
  // can create a table at version 1 and then close it again
  // so that LazyOpen sees there is work to do (LazyOpen will return
  // early if the database is already open).
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");

  DomStorageDatabase db(file_name);
  db.db_.reset(new sql::Connection());
  ASSERT_TRUE(db.db_->Open(file_name));
  CreateV1Table(db.db_.get());
  db.Close();

  EXPECT_TRUE(db.LazyOpen(true));
  EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());
}

TEST(DomStorageDatabaseTest, SimpleWriteAndReadBack) {
  DomStorageDatabase db;

  ValuesMap storage;
  CreateMapWithValues(&storage);

  EXPECT_TRUE(db.CommitChanges(false, storage));
  CheckValuesMatch(&db, storage);
}

TEST(DomStorageDatabaseTest, WriteWithClear) {
  DomStorageDatabase db;

  ValuesMap storage;
  CreateMapWithValues(&storage);

  ASSERT_TRUE(db.CommitChanges(false, storage));
  CheckValuesMatch(&db, storage);

  // Insert some values, clearing the database first.
  storage.clear();
  storage[ASCIIToUTF16("another_key")] =
      NullableString16(ASCIIToUTF16("test"), false);
  ASSERT_TRUE(db.CommitChanges(true, storage));
  CheckValuesMatch(&db, storage);

  // Now clear the values without inserting any new ones.
  storage.clear();
  ASSERT_TRUE(db.CommitChanges(true, storage));
  CheckValuesMatch(&db, storage);
}

TEST(DomStorageDatabaseTest, UpgradeFromV1ToV2WithData) {
  const string16 kCannedKey = ASCIIToUTF16("foo");
  const NullableString16 kCannedValue(ASCIIToUTF16("bar"), false);
  ValuesMap expected;
  expected[kCannedKey] = kCannedValue;

  DomStorageDatabase db;
  db.db_.reset(new sql::Connection());
  ASSERT_TRUE(db.db_->OpenInMemory());
  CreateV1Table(db.db_.get());
  InsertDataV1(db.db_.get(), kCannedKey, kCannedValue.string());

  ASSERT_TRUE(db.UpgradeVersion1To2());

  EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());

  CheckValuesMatch(&db, expected);
}

TEST(DomStorageDatabaseTest, TestSimpleRemoveOneValue) {
  DomStorageDatabase db;

  ASSERT_TRUE(db.LazyOpen(true));
  const string16 kCannedKey = ASCIIToUTF16("test");
  const NullableString16 kCannedValue(ASCIIToUTF16("data"), false);
  ValuesMap expected;
  expected[kCannedKey] = kCannedValue;

  // First write some data into the database.
  ASSERT_TRUE(db.CommitChanges(false, expected));
  CheckValuesMatch(&db, expected);

  ValuesMap values;
  // A null string in the map should mean that that key gets
  // removed.
  values[kCannedKey] = NullableString16(true);
  EXPECT_TRUE(db.CommitChanges(false, values));

  expected.clear();
  CheckValuesMatch(&db, expected);
}

TEST(DomStorageDatabaseTest, TestCanOpenAndReadWebCoreDatabase) {
  FilePath webcore_database;
  PathService::Get(base::DIR_SOURCE_ROOT, &webcore_database);
  webcore_database = webcore_database.AppendASCII("webkit");
  webcore_database = webcore_database.AppendASCII("data");
  webcore_database = webcore_database.AppendASCII("dom_storage");
  webcore_database =
      webcore_database.AppendASCII("webcore_test_database.localstorage");

  ASSERT_TRUE(file_util::PathExists(webcore_database));

  DomStorageDatabase db(webcore_database);
  ValuesMap values;
  db.ReadAllValues(&values);
  EXPECT_TRUE(db.IsOpen());
  EXPECT_EQ(2u, values.size());

  ValuesMap::const_iterator it =
      values.find(ASCIIToUTF16("value"));
  EXPECT_TRUE(it != values.end());
  EXPECT_EQ(ASCIIToUTF16("I am in local storage!"), it->second.string());

  it = values.find(ASCIIToUTF16("timestamp"));
  EXPECT_TRUE(it != values.end());
  EXPECT_EQ(ASCIIToUTF16("1326738338841"), it->second.string());

  it = values.find(ASCIIToUTF16("not_there"));
  EXPECT_TRUE(it == values.end());
}

TEST(DomStorageDatabaseTest, TestCanOpenFileThatIsNotADatabase) {
  // Write into the temporary file first.
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");

  const char kData[] = "I am not a database.";
  file_util::WriteFile(file_name, kData, strlen(kData));

  {
    // Try and open the file. As it's not a database, we should end up deleting
    // it and creating a new, valid file, so everything should actually
    // succeed.
    DomStorageDatabase db(file_name);
    ValuesMap values;
    CreateMapWithValues(&values);
    EXPECT_TRUE(db.CommitChanges(true, values));
    EXPECT_TRUE(db.CommitChanges(false, values));
    EXPECT_TRUE(db.IsOpen());

    CheckValuesMatch(&db, values);
  }

  {
    // Try to open a directory, we should fail gracefully and not attempt
    // to delete it.
    DomStorageDatabase db(temp_dir.path());
    ValuesMap values;
    CreateMapWithValues(&values);
    EXPECT_FALSE(db.CommitChanges(true, values));
    EXPECT_FALSE(db.CommitChanges(false, values));
    EXPECT_FALSE(db.IsOpen());

    values.clear();

    db.ReadAllValues(&values);
    EXPECT_EQ(0u, values.size());
    EXPECT_FALSE(db.IsOpen());

    EXPECT_TRUE(file_util::PathExists(temp_dir.path()));
  }
}

}  // namespace dom_storage
<commit_msg>webkit: Instead of doing a conversion just use string16().<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/dom_storage/dom_storage_database.h"

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/scoped_temp_dir.h"
#include "base/utf_string_conversions.h"
#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace dom_storage {

void CreateV1Table(sql::Connection* db) {
  ASSERT_TRUE(db->is_open());
  ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
  ASSERT_TRUE(db->Execute(
      "CREATE TABLE ItemTable ("
      "key TEXT UNIQUE ON CONFLICT REPLACE, "
      "value TEXT NOT NULL ON CONFLICT FAIL)"));
}

void CreateV2Table(sql::Connection* db) {
  ASSERT_TRUE(db->is_open());
  ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
  ASSERT_TRUE(db->Execute(
      "CREATE TABLE ItemTable ("
      "key TEXT UNIQUE ON CONFLICT REPLACE, "
      "value BLOB NOT NULL ON CONFLICT FAIL)"));
}

void CreateInvalidKeyColumnTable(sql::Connection* db) {
  // Create a table with the key type as FLOAT - this is "invalid"
  // as far as the DOM Storage db is concerned.
  ASSERT_TRUE(db->is_open());
  ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
  ASSERT_TRUE(db->Execute(
      "CREATE TABLE IF NOT EXISTS ItemTable ("
      "key FLOAT UNIQUE ON CONFLICT REPLACE, "
      "value BLOB NOT NULL ON CONFLICT FAIL)"));
}
void CreateInvalidValueColumnTable(sql::Connection* db) {
  // Create a table with the value type as FLOAT - this is "invalid"
  // as far as the DOM Storage db is concerned.
  ASSERT_TRUE(db->is_open());
  ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
  ASSERT_TRUE(db->Execute(
      "CREATE TABLE IF NOT EXISTS ItemTable ("
      "key TEXT UNIQUE ON CONFLICT REPLACE, "
      "value FLOAT NOT NULL ON CONFLICT FAIL)"));
}

void InsertDataV1(sql::Connection* db,
                  const string16& key,
                  const string16& value) {
  sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE,
      "INSERT INTO ItemTable VALUES (?,?)"));
  statement.BindString16(0, key);
  statement.BindString16(1, value);
  ASSERT_TRUE(statement.is_valid());
  statement.Run();
}

void CheckValuesMatch(DomStorageDatabase* db,
                      const ValuesMap& expected) {
  ValuesMap values_read;
  db->ReadAllValues(&values_read);
  EXPECT_EQ(expected.size(), values_read.size());

  ValuesMap::const_iterator it = values_read.begin();
  for (; it != values_read.end(); ++it) {
    string16 key = it->first;
    NullableString16 value = it->second;
    NullableString16 expected_value = expected.find(key)->second;
    EXPECT_EQ(expected_value.string(), value.string());
    EXPECT_EQ(expected_value.is_null(), value.is_null());
  }
}

void CreateMapWithValues(ValuesMap* values) {
  string16 kCannedKeys[] = {
      ASCIIToUTF16("test"),
      ASCIIToUTF16("company"),
      ASCIIToUTF16("date"),
      ASCIIToUTF16("empty")
  };
  NullableString16 kCannedValues[] = {
      NullableString16(ASCIIToUTF16("123"), false),
      NullableString16(ASCIIToUTF16("Google"), false),
      NullableString16(ASCIIToUTF16("18-01-2012"), false),
      NullableString16(string16(), false)
  };
  for (unsigned i = 0; i < sizeof(kCannedKeys) / sizeof(kCannedKeys[0]); i++)
    (*values)[kCannedKeys[i]] = kCannedValues[i];
}

TEST(DomStorageDatabaseTest, SimpleOpenAndClose) {
  DomStorageDatabase db;
  EXPECT_FALSE(db.IsOpen());
  ASSERT_TRUE(db.LazyOpen(true));
  EXPECT_TRUE(db.IsOpen());
  EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());
  db.Close();
  EXPECT_FALSE(db.IsOpen());
}

TEST(DomStorageDatabaseTest, CloseEmptyDatabaseDeletesFile) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");
  ValuesMap storage;
  CreateMapWithValues(&storage);

  // First test the case that explicitly clearing the database will
  // trigger its deletion from disk.
  {
    DomStorageDatabase db(file_name);
    EXPECT_EQ(file_name, db.file_path());
    ASSERT_TRUE(db.CommitChanges(false, storage));
  }
  EXPECT_TRUE(file_util::PathExists(file_name));

  {
    // Check that reading an existing db with data in it
    // keeps the DB on disk on close.
    DomStorageDatabase db(file_name);
    ValuesMap values;
    db.ReadAllValues(&values);
    EXPECT_EQ(storage.size(), values.size());
  }

  EXPECT_TRUE(file_util::PathExists(file_name));
  storage.clear();

  {
    DomStorageDatabase db(file_name);
    ASSERT_TRUE(db.CommitChanges(true, storage));
  }
  EXPECT_FALSE(file_util::PathExists(file_name));

  // Now ensure that a series of updates and removals whose net effect
  // is an empty database also triggers deletion.
  CreateMapWithValues(&storage);
  {
    DomStorageDatabase db(file_name);
    ASSERT_TRUE(db.CommitChanges(false, storage));
  }

  EXPECT_TRUE(file_util::PathExists(file_name));

  {
    DomStorageDatabase db(file_name);
    ASSERT_TRUE(db.CommitChanges(false, storage));
    ValuesMap::iterator it = storage.begin();
    for (; it != storage.end(); ++it)
      it->second = NullableString16(true);
    ASSERT_TRUE(db.CommitChanges(false, storage));
  }
  EXPECT_FALSE(file_util::PathExists(file_name));
}

TEST(DomStorageDatabaseTest, TestLazyOpenIsLazy) {
  // This test needs to operate with a file on disk to ensure that we will
  // open a file that already exists when only invoking ReadAllValues.
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");

  DomStorageDatabase db(file_name);
  EXPECT_FALSE(db.IsOpen());
  ValuesMap values;
  db.ReadAllValues(&values);
  // Reading an empty db should not open the database.
  EXPECT_FALSE(db.IsOpen());

  values[ASCIIToUTF16("key")] = NullableString16(ASCIIToUTF16("value"), false);
  db.CommitChanges(false, values);
  // Writing content should open the database.
  EXPECT_TRUE(db.IsOpen());

  db.Close();
  ASSERT_FALSE(db.IsOpen());

  // Reading from an existing database should open the database.
  CheckValuesMatch(&db, values);
  EXPECT_TRUE(db.IsOpen());
}

TEST(DomStorageDatabaseTest, TestDetectSchemaVersion) {
  DomStorageDatabase db;
  db.db_.reset(new sql::Connection());
  ASSERT_TRUE(db.db_->OpenInMemory());

  CreateInvalidValueColumnTable(db.db_.get());
  EXPECT_EQ(DomStorageDatabase::INVALID, db.DetectSchemaVersion());

  CreateInvalidKeyColumnTable(db.db_.get());
  EXPECT_EQ(DomStorageDatabase::INVALID, db.DetectSchemaVersion());

  CreateV1Table(db.db_.get());
  EXPECT_EQ(DomStorageDatabase::V1, db.DetectSchemaVersion());

  CreateV2Table(db.db_.get());
  EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());
}

TEST(DomStorageDatabaseTest, TestLazyOpenUpgradesDatabase) {
  // This test needs to operate with a file on disk so that we
  // can create a table at version 1 and then close it again
  // so that LazyOpen sees there is work to do (LazyOpen will return
  // early if the database is already open).
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");

  DomStorageDatabase db(file_name);
  db.db_.reset(new sql::Connection());
  ASSERT_TRUE(db.db_->Open(file_name));
  CreateV1Table(db.db_.get());
  db.Close();

  EXPECT_TRUE(db.LazyOpen(true));
  EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());
}

TEST(DomStorageDatabaseTest, SimpleWriteAndReadBack) {
  DomStorageDatabase db;

  ValuesMap storage;
  CreateMapWithValues(&storage);

  EXPECT_TRUE(db.CommitChanges(false, storage));
  CheckValuesMatch(&db, storage);
}

TEST(DomStorageDatabaseTest, WriteWithClear) {
  DomStorageDatabase db;

  ValuesMap storage;
  CreateMapWithValues(&storage);

  ASSERT_TRUE(db.CommitChanges(false, storage));
  CheckValuesMatch(&db, storage);

  // Insert some values, clearing the database first.
  storage.clear();
  storage[ASCIIToUTF16("another_key")] =
      NullableString16(ASCIIToUTF16("test"), false);
  ASSERT_TRUE(db.CommitChanges(true, storage));
  CheckValuesMatch(&db, storage);

  // Now clear the values without inserting any new ones.
  storage.clear();
  ASSERT_TRUE(db.CommitChanges(true, storage));
  CheckValuesMatch(&db, storage);
}

TEST(DomStorageDatabaseTest, UpgradeFromV1ToV2WithData) {
  const string16 kCannedKey = ASCIIToUTF16("foo");
  const NullableString16 kCannedValue(ASCIIToUTF16("bar"), false);
  ValuesMap expected;
  expected[kCannedKey] = kCannedValue;

  DomStorageDatabase db;
  db.db_.reset(new sql::Connection());
  ASSERT_TRUE(db.db_->OpenInMemory());
  CreateV1Table(db.db_.get());
  InsertDataV1(db.db_.get(), kCannedKey, kCannedValue.string());

  ASSERT_TRUE(db.UpgradeVersion1To2());

  EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());

  CheckValuesMatch(&db, expected);
}

TEST(DomStorageDatabaseTest, TestSimpleRemoveOneValue) {
  DomStorageDatabase db;

  ASSERT_TRUE(db.LazyOpen(true));
  const string16 kCannedKey = ASCIIToUTF16("test");
  const NullableString16 kCannedValue(ASCIIToUTF16("data"), false);
  ValuesMap expected;
  expected[kCannedKey] = kCannedValue;

  // First write some data into the database.
  ASSERT_TRUE(db.CommitChanges(false, expected));
  CheckValuesMatch(&db, expected);

  ValuesMap values;
  // A null string in the map should mean that that key gets
  // removed.
  values[kCannedKey] = NullableString16(true);
  EXPECT_TRUE(db.CommitChanges(false, values));

  expected.clear();
  CheckValuesMatch(&db, expected);
}

TEST(DomStorageDatabaseTest, TestCanOpenAndReadWebCoreDatabase) {
  FilePath webcore_database;
  PathService::Get(base::DIR_SOURCE_ROOT, &webcore_database);
  webcore_database = webcore_database.AppendASCII("webkit");
  webcore_database = webcore_database.AppendASCII("data");
  webcore_database = webcore_database.AppendASCII("dom_storage");
  webcore_database =
      webcore_database.AppendASCII("webcore_test_database.localstorage");

  ASSERT_TRUE(file_util::PathExists(webcore_database));

  DomStorageDatabase db(webcore_database);
  ValuesMap values;
  db.ReadAllValues(&values);
  EXPECT_TRUE(db.IsOpen());
  EXPECT_EQ(2u, values.size());

  ValuesMap::const_iterator it =
      values.find(ASCIIToUTF16("value"));
  EXPECT_TRUE(it != values.end());
  EXPECT_EQ(ASCIIToUTF16("I am in local storage!"), it->second.string());

  it = values.find(ASCIIToUTF16("timestamp"));
  EXPECT_TRUE(it != values.end());
  EXPECT_EQ(ASCIIToUTF16("1326738338841"), it->second.string());

  it = values.find(ASCIIToUTF16("not_there"));
  EXPECT_TRUE(it == values.end());
}

TEST(DomStorageDatabaseTest, TestCanOpenFileThatIsNotADatabase) {
  // Write into the temporary file first.
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");

  const char kData[] = "I am not a database.";
  file_util::WriteFile(file_name, kData, strlen(kData));

  {
    // Try and open the file. As it's not a database, we should end up deleting
    // it and creating a new, valid file, so everything should actually
    // succeed.
    DomStorageDatabase db(file_name);
    ValuesMap values;
    CreateMapWithValues(&values);
    EXPECT_TRUE(db.CommitChanges(true, values));
    EXPECT_TRUE(db.CommitChanges(false, values));
    EXPECT_TRUE(db.IsOpen());

    CheckValuesMatch(&db, values);
  }

  {
    // Try to open a directory, we should fail gracefully and not attempt
    // to delete it.
    DomStorageDatabase db(temp_dir.path());
    ValuesMap values;
    CreateMapWithValues(&values);
    EXPECT_FALSE(db.CommitChanges(true, values));
    EXPECT_FALSE(db.CommitChanges(false, values));
    EXPECT_FALSE(db.IsOpen());

    values.clear();

    db.ReadAllValues(&values);
    EXPECT_EQ(0u, values.size());
    EXPECT_FALSE(db.IsOpen());

    EXPECT_TRUE(file_util::PathExists(temp_dir.path()));
  }
}

}  // namespace dom_storage
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <cmath>
#include "simulator.h"
#include "core_manager.h"
#include "config.h"
#include "core.h"
#include "network.h"
#include "network_model.h"
#include "clock_skew_minimization_object.h"
#include "carbon_user.h"
#include "utils.h"

class RandNum
{
   public:
      RandNum(double start, double end):
         _start(start), _end(end)
      {
         srand48_r(time(NULL), &rand_buffer);
      }
      ~RandNum() {}
      double next()
      {
         double result;
         drand48_r(&rand_buffer, &result);
         return (result * (_end - _start) + _start);
      }

   private:
      struct drand48_data rand_buffer;
      double _start;
      double _end;
};

enum NetworkTrafficType
{
   UNIFORM_RANDOM = 0,
   BIT_COMPLEMENT,
   SHUFFLE,
   TRANSPOSE,
   TORNADO,
   NEAREST_NEIGHBOR,
   NUM_NETWORK_TRAFFIC_TYPES
};

void* sendNetworkTraffic(void*);
void uniformRandomTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);
void bitComplementTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);
void shuffleTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);
void transposeTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);
void tornadoTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);
void nearestNeighborTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);

bool canSendPacket(double offered_load, RandNum& rand_num);
void synchronize(UInt64 time, Core* core);
void printHelpMessage();
NetworkTrafficType parseTrafficPattern(string traffic_pattern);

NetworkTrafficType _traffic_pattern_type = UNIFORM_RANDOM;     // Network Traffic Pattern Type
double _offered_load = 0.1;                                    // Number of packets injected per core per cycle
SInt32 _packet_size = 8;                                       // Size of each Packet in Bytes
UInt64 _total_packets = 10000;                                 // Total number of packets injected into the network per core

PacketType _packet_type = USER_2;                              // Type of each packet (so as to send on 2nd user network)
carbon_barrier_t _global_barrier;
SInt32 _num_cores;

int main(int argc, char* argv[])
{
   CarbonStartSim(argc, argv);

   Simulator::enablePerformanceModelsInCurrentProcess();

   // Read Command Line Arguments
   for (SInt32 i = 1; i < argc-1; i += 2)
   {
      if (string(argv[i]) == "-p")
         _traffic_pattern_type = parseTrafficPattern(string(argv[i+1]));
      else if (string(argv[i]) == "-l")
         _offered_load = (double) atof(argv[i+1]);
      else if (string(argv[i]) == "-s")
         _packet_size = (SInt32) atoi(argv[i+1]);
      else if (string(argv[i]) == "-N")
         _total_packets = (UInt64) atoi(argv[i+1]);
      else if (string(argv[i]) == "-c") // Simulator arguments
         break;
      else if (string(argv[i]) == "-h")
      {
         printHelpMessage();
         exit(0);
      }
      else
      {
         fprintf(stderr, "** ERROR **\n");
         printHelpMessage();
         exit(-1);
      }
   }

   _num_cores = (SInt32) Config::getSingleton()->getApplicationCores();
   CarbonBarrierInit(&_global_barrier, _num_cores);

   carbon_thread_t tid_list[_num_cores-1];
   for (SInt32 i = 0; i < _num_cores-1; i++)
   {
      tid_list[i] = CarbonSpawnThread(sendNetworkTraffic, NULL);
   }
   sendNetworkTraffic(NULL);

   for (SInt32 i = 0; i < _num_cores-1; i++)
   {
      CarbonJoinThread(tid_list[i]);
   }

   printf("Joined all threads\n");

   Simulator::disablePerformanceModelsInCurrentProcess();

   CarbonStopSim();

   return 0;
}

void printHelpMessage()
{
   fprintf(stderr, "[Usage]: ./synthetic_network_traffic_generator -p <arg1> -l <arg2> -s <arg3> -N <arg4>\n");
   fprintf(stderr, "where <arg1> = Network Traffic Pattern Type (uniform_random, bit_complement, shuffle, transpose, tornado, nearest_neighbor) (default uniform_random)\n");
   fprintf(stderr, " and  <arg2> = Number of Packets injected into the Network per Core per Cycle (default 0.1)\n");
   fprintf(stderr, " and  <arg3> = Size of each Packet in Bytes (default 8)\n");
   fprintf(stderr, " and  <arg4> = Total Number of Packets injected into the Network per Core (default 10000)\n");
}

NetworkTrafficType parseTrafficPattern(string traffic_pattern)
{
   if (traffic_pattern == "uniform_random")
      return UNIFORM_RANDOM;
   else if (traffic_pattern == "bit_complement")
      return BIT_COMPLEMENT;
   else if (traffic_pattern == "shuffle")
      return SHUFFLE;
   else if (traffic_pattern == "transpose")
      return TRANSPOSE;
   else if (traffic_pattern == "tornado")
      return TORNADO;
   else if (traffic_pattern == "nearest_neighbor")
      return NEAREST_NEIGHBOR;
   else
   {
      fprintf(stderr, "** ERROR **\n");
      fprintf(stderr, "Unrecognized Network Traffic Pattern Type (Use uniform_random, bit_complement, shuffle, transpose, tornado, nearest_neighbor)\n");
      exit(-1);
   }
}

void* sendNetworkTraffic(void*)
{
   // Wait for everyone to be spawned
   CarbonBarrierWait(&_global_barrier);

   Core* core = Sim()->getCoreManager()->getCurrentCore();

   vector<int> send_vec;
   vector<int> receive_vec;

   // Generate the Network Traffic
   switch (_traffic_pattern_type)
   {
      case UNIFORM_RANDOM:
         uniformRandomTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      case BIT_COMPLEMENT:
         bitComplementTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      case SHUFFLE:
         shuffleTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      case TRANSPOSE:
         transposeTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      case TORNADO:
         tornadoTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      case NEAREST_NEIGHBOR:
         nearestNeighborTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      default:
         assert(false);
         break;
   }

   Byte data[_packet_size];
   UInt64 outstanding_window_size = 1000;
   RandNum rand_num(0,1);

   for (UInt64 time = 0, total_packets_sent = 0, total_packets_received = 0;
         (total_packets_sent < _total_packets) || (total_packets_received < _total_packets);
         time ++)
   {
      if ((total_packets_sent < _total_packets) && (canSendPacket(_offered_load, rand_num)))
      {
         // Send a packet to its destination core
         SInt32 receiver = send_vec[total_packets_sent % send_vec.size()];
         NetPacket net_packet(time, _packet_type, core->getId(), receiver, _packet_size, data);
         core->getNetwork()->netSend(net_packet);
         total_packets_sent ++;
      }

      if (total_packets_sent < _total_packets)
      {
         // Synchronize after every few cycles
         synchronize(time, core);
      }

      if ( (total_packets_received < _total_packets) &&
           ( (total_packets_sent == _total_packets) ||
             (total_packets_sent >= (total_packets_received + outstanding_window_size)) ) )
      {
         // Check if a packet has arrived for this core (Should be non-blocking)
         NetPacket recv_net_packet = core->getNetwork()->netRecvType(_packet_type);
         delete [] (Byte*) recv_net_packet.data;
         total_packets_received ++;
      }
   }

   // Wait for everyone to finish
   CarbonBarrierWait(&_global_barrier);
   return NULL;
}

bool canSendPacket(double offered_load, RandNum& rand_num)
{
   return (rand_num.next() < offered_load);
}

void synchronize(UInt64 packet_injection_time, Core* core)
{
   ClockSkewMinimizationClient* clock_skew_client = core->getClockSkewMinimizationClient();

   if (clock_skew_client)
      clock_skew_client->synchronize(packet_injection_time);
}

void computeEMeshTopologyParams(int num_cores, int& mesh_width, int& mesh_height);
void computeEMeshPosition(int core_id, int& sx, int& sy, int mesh_width);
int computeCoreId(int sx, int sy, int mesh_width);

void uniformRandomTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec)
{
   // Generate Random Numbers using Linear Congruential Generator
   int send_matrix[_num_cores][_num_cores];
   int receive_matrix[_num_cores][_num_cores];

   send_matrix[0][0] = _num_cores / 2; // Initial seed
   receive_matrix[0][send_matrix[0][0]] = 0;
   for (int i = 0; i < _num_cores; i++) // Time Slot
   {
      if (i != 0)
      {
         send_matrix[i][0] = send_matrix[i-1][1];
         receive_matrix[i][send_matrix[i][0]] = 0;
      }
      for (int j = 1; j < _num_cores; j++) // Sender
      {
         send_matrix[i][j] = (13 * send_matrix[i][j-1] + 5) % _num_cores;
         receive_matrix[i][send_matrix[i][j]] = j;
      }
   }

   // Check the validity of the random numbers
   for (int i = 0; i < _num_cores; i++) // Time Slot
   {
      vector<bool> bits(_num_cores, false);
      for (int j = 0; j < _num_cores; j++) // Sender
      {
         bits[send_matrix[i][j]] = true;
      }
      for (int j = 0; j < _num_cores; j++)
      {
         assert(bits[j]);
      }
   }

   for (int j = 0; j < _num_cores; j++) // Sender
   {
      vector<bool> bits(_num_cores, false);
      for (int i = 0; i < _num_cores; i++) // Time Slot
      {
         bits[send_matrix[i][j]] = true;
      }
      for (int i = 0; i < _num_cores; i++)
      {
         assert(bits[i]);
      }
   }

   for (SInt32 i = 0; i < _num_cores; i++)
   {
      send_vec.push_back(send_matrix[i][core_id]);
      receive_vec.push_back(receive_matrix[i][core_id]);
   }
}

void bitComplementTrafficGenerator(int core_id, vector<core_id_t>& send_vec, vector<core_id_t>& receive_vec)
{
   assert(isPower2(_num_cores));
   int mask = _num_cores-1;
   int dst_core = (~core_id) & mask;
   send_vec.push_back(dst_core);
   receive_vec.push_back(dst_core);
}

void shuffleTrafficGenerator(int core_id, vector<core_id_t>& send_vec, vector<core_id_t>& receive_vec)
{
   assert(isPower2(_num_cores));
   int mask = _num_cores-1;
   int nbits = floorLog2(_num_cores);
   int dst_core = ((core_id >> (nbits-1)) & 1) | ((core_id << 1) & mask);
   send_vec.push_back(dst_core);
   receive_vec.push_back(dst_core);
}

void transposeTrafficGenerator(int core_id, vector<core_id_t>& send_vec, vector<core_id_t>& receive_vec)
{
   int mesh_width, mesh_height;
   computeEMeshTopologyParams(_num_cores, mesh_width, mesh_height);
   int sx, sy;
   computeEMeshPosition(core_id, sx, sy, mesh_width);
   int dst_core = computeCoreId(sy, sx, mesh_width);

   send_vec.push_back(dst_core);
   receive_vec.push_back(dst_core);
}

void tornadoTrafficGenerator(int core_id, vector<core_id_t>& send_vec, vector<core_id_t>& receive_vec)
{
   int mesh_width, mesh_height;
   computeEMeshTopologyParams(_num_cores, mesh_width, mesh_height);
   int sx, sy;
   computeEMeshPosition(core_id, sx, sy, mesh_width);
   int dst_core = computeCoreId((sx + mesh_width/2) % mesh_width, (sy + mesh_height/2) % mesh_height, mesh_width);
}

void nearestNeighborTrafficGenerator(int core_id, vector<core_id_t>& send_vec, vector<core_id_t>& receive_vec)
{
   int mesh_width, mesh_height;
   computeEMeshTopologyParams(_num_cores, mesh_width, mesh_height);
   int sx, sy;
   computeEMeshPosition(core_id, sx, sy, mesh_width);
   int dst_core = computeCoreId((sx+1) % mesh_width, (sy+1) % mesh_height, mesh_width);

   send_vec.push_back(dst_core);
   receive_vec.push_back(dst_core);
}

void computeEMeshTopologyParams(int num_cores, int& mesh_width, int& mesh_height)
{
   mesh_width = (int) sqrt((float) num_cores);
   mesh_height = (int) ceil(1.0 * num_cores / mesh_width);
   assert(num_cores == (mesh_width * mesh_height));
}

void computeEMeshPosition(int core_id, int& sx, int& sy, int mesh_width)
{
   sx = core_id % mesh_width;
   sy = core_id / mesh_width;
}

int computeCoreId(int sx, int sy, int mesh_width)
{
   return ((sy * mesh_width) + sx);
}
<commit_msg>[tests] Fixed the synthetic network traffic models after network API changes<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <cmath>
#include "simulator.h"
#include "core_manager.h"
#include "config.h"
#include "core.h"
#include "network.h"
#include "network_model.h"
#include "clock_skew_minimization_object.h"
#include "carbon_user.h"
#include "utils.h"

class RandNum
{
   public:
      RandNum(double start, double end):
         _start(start), _end(end)
      {
         srand48_r(time(NULL), &rand_buffer);
      }
      ~RandNum() {}
      double next()
      {
         double result;
         drand48_r(&rand_buffer, &result);
         return (result * (_end - _start) + _start);
      }

   private:
      struct drand48_data rand_buffer;
      double _start;
      double _end;
};

enum NetworkTrafficType
{
   UNIFORM_RANDOM = 0,
   BIT_COMPLEMENT,
   SHUFFLE,
   TRANSPOSE,
   TORNADO,
   NEAREST_NEIGHBOR,
   NUM_NETWORK_TRAFFIC_TYPES
};

void* sendNetworkTraffic(void*);
void uniformRandomTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);
void bitComplementTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);
void shuffleTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);
void transposeTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);
void tornadoTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);
void nearestNeighborTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec);

bool canSendPacket(double offered_load, RandNum& rand_num);
void synchronize(UInt64 time, Core* core);
void printHelpMessage();
NetworkTrafficType parseTrafficPattern(string traffic_pattern);

NetworkTrafficType _traffic_pattern_type = UNIFORM_RANDOM;     // Network Traffic Pattern Type
double _offered_load = 0.1;                                    // Number of packets injected per core per cycle
SInt32 _packet_size = 8;                                       // Size of each Packet in Bytes
UInt64 _total_packets = 10000;                                 // Total number of packets injected into the network per core

PacketType _packet_type = USER_2;                              // Type of each packet (so as to send on 2nd user network)
carbon_barrier_t _global_barrier;
SInt32 _num_cores;

int main(int argc, char* argv[])
{
   CarbonStartSim(argc, argv);

   Simulator::enablePerformanceModelsInCurrentProcess();

   // Read Command Line Arguments
   for (SInt32 i = 1; i < argc-1; i += 2)
   {
      if (string(argv[i]) == "-p")
         _traffic_pattern_type = parseTrafficPattern(string(argv[i+1]));
      else if (string(argv[i]) == "-l")
         _offered_load = (double) atof(argv[i+1]);
      else if (string(argv[i]) == "-s")
         _packet_size = (SInt32) atoi(argv[i+1]);
      else if (string(argv[i]) == "-N")
         _total_packets = (UInt64) atoi(argv[i+1]);
      else if (string(argv[i]) == "-c") // Simulator arguments
         break;
      else if (string(argv[i]) == "-h")
      {
         printHelpMessage();
         exit(0);
      }
      else
      {
         fprintf(stderr, "** ERROR **\n");
         printHelpMessage();
         exit(-1);
      }
   }

   _num_cores = (SInt32) Config::getSingleton()->getApplicationCores();
   CarbonBarrierInit(&_global_barrier, _num_cores);

   carbon_thread_t tid_list[_num_cores-1];
   for (SInt32 i = 0; i < _num_cores-1; i++)
   {
      tid_list[i] = CarbonSpawnThread(sendNetworkTraffic, NULL);
   }
   sendNetworkTraffic(NULL);

   for (SInt32 i = 0; i < _num_cores-1; i++)
   {
      CarbonJoinThread(tid_list[i]);
   }

   printf("Joined all threads\n");

   Simulator::disablePerformanceModelsInCurrentProcess();

   CarbonStopSim();

   return 0;
}

void printHelpMessage()
{
   fprintf(stderr, "[Usage]: ./synthetic_network_traffic_generator -p <arg1> -l <arg2> -s <arg3> -N <arg4>\n");
   fprintf(stderr, "where <arg1> = Network Traffic Pattern Type (uniform_random, bit_complement, shuffle, transpose, tornado, nearest_neighbor) (default uniform_random)\n");
   fprintf(stderr, " and  <arg2> = Number of Packets injected into the Network per Core per Cycle (default 0.1)\n");
   fprintf(stderr, " and  <arg3> = Size of each Packet in Bytes (default 8)\n");
   fprintf(stderr, " and  <arg4> = Total Number of Packets injected into the Network per Core (default 10000)\n");
}

NetworkTrafficType parseTrafficPattern(string traffic_pattern)
{
   if (traffic_pattern == "uniform_random")
      return UNIFORM_RANDOM;
   else if (traffic_pattern == "bit_complement")
      return BIT_COMPLEMENT;
   else if (traffic_pattern == "shuffle")
      return SHUFFLE;
   else if (traffic_pattern == "transpose")
      return TRANSPOSE;
   else if (traffic_pattern == "tornado")
      return TORNADO;
   else if (traffic_pattern == "nearest_neighbor")
      return NEAREST_NEIGHBOR;
   else
   {
      fprintf(stderr, "** ERROR **\n");
      fprintf(stderr, "Unrecognized Network Traffic Pattern Type (Use uniform_random, bit_complement, shuffle, transpose, tornado, nearest_neighbor)\n");
      exit(-1);
   }
}

void* sendNetworkTraffic(void*)
{
   // Wait for everyone to be spawned
   CarbonBarrierWait(&_global_barrier);

   Core* core = Sim()->getCoreManager()->getCurrentCore();

   vector<int> send_vec;
   vector<int> receive_vec;

   // Generate the Network Traffic
   switch (_traffic_pattern_type)
   {
      case UNIFORM_RANDOM:
         uniformRandomTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      case BIT_COMPLEMENT:
         bitComplementTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      case SHUFFLE:
         shuffleTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      case TRANSPOSE:
         transposeTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      case TORNADO:
         tornadoTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      case NEAREST_NEIGHBOR:
         nearestNeighborTrafficGenerator(core->getId(), send_vec, receive_vec);
         break;
      default:
         assert(false);
         break;
   }

   Byte data[_packet_size];
   UInt64 outstanding_window_size = 1000;
   RandNum rand_num(0,1);

   for (UInt64 time = 0, total_packets_sent = 0, total_packets_received = 0;
         (total_packets_sent < _total_packets) || (total_packets_received < _total_packets);
         time ++)
   {
      if ((total_packets_sent < _total_packets) && (canSendPacket(_offered_load, rand_num)))
      {
         // Send a packet to its destination core
         SInt32 receiver = send_vec[total_packets_sent % send_vec.size()];
         NetPacket net_packet(time, _packet_type, core->getId(), receiver, _packet_size, data);
         core->getNetwork()->netSend(net_packet);
         total_packets_sent ++;
      }

      if (total_packets_sent < _total_packets)
      {
         // Synchronize after every few cycles
         synchronize(time, core);
      }

      if ( (total_packets_received < _total_packets) &&
           ( (total_packets_sent == _total_packets) ||
             (total_packets_sent >= (total_packets_received + outstanding_window_size)) ) )
      {
         // Check if a packet has arrived for this core (Should be non-blocking)
         NetPacket* recv_net_packet = core->getNetwork()->netRecvType(_packet_type);
         recv_net_packet->release();
         total_packets_received ++;
      }
   }

   // Wait for everyone to finish
   CarbonBarrierWait(&_global_barrier);
   return NULL;
}

bool canSendPacket(double offered_load, RandNum& rand_num)
{
   return (rand_num.next() < offered_load);
}

void synchronize(UInt64 packet_injection_time, Core* core)
{
   ClockSkewMinimizationClient* clock_skew_client = core->getClockSkewMinimizationClient();

   if (clock_skew_client)
      clock_skew_client->synchronize(packet_injection_time);
}

void computeEMeshTopologyParams(int num_cores, int& mesh_width, int& mesh_height);
void computeEMeshPosition(int core_id, int& sx, int& sy, int mesh_width);
int computeCoreId(int sx, int sy, int mesh_width);

void uniformRandomTrafficGenerator(int core_id, vector<int>& send_vec, vector<int>& receive_vec)
{
   // Generate Random Numbers using Linear Congruential Generator
   int send_matrix[_num_cores][_num_cores];
   int receive_matrix[_num_cores][_num_cores];

   send_matrix[0][0] = _num_cores / 2; // Initial seed
   receive_matrix[0][send_matrix[0][0]] = 0;
   for (int i = 0; i < _num_cores; i++) // Time Slot
   {
      if (i != 0)
      {
         send_matrix[i][0] = send_matrix[i-1][1];
         receive_matrix[i][send_matrix[i][0]] = 0;
      }
      for (int j = 1; j < _num_cores; j++) // Sender
      {
         send_matrix[i][j] = (13 * send_matrix[i][j-1] + 5) % _num_cores;
         receive_matrix[i][send_matrix[i][j]] = j;
      }
   }

   // Check the validity of the random numbers
   for (int i = 0; i < _num_cores; i++) // Time Slot
   {
      vector<bool> bits(_num_cores, false);
      for (int j = 0; j < _num_cores; j++) // Sender
      {
         bits[send_matrix[i][j]] = true;
      }
      for (int j = 0; j < _num_cores; j++)
      {
         assert(bits[j]);
      }
   }

   for (int j = 0; j < _num_cores; j++) // Sender
   {
      vector<bool> bits(_num_cores, false);
      for (int i = 0; i < _num_cores; i++) // Time Slot
      {
         bits[send_matrix[i][j]] = true;
      }
      for (int i = 0; i < _num_cores; i++)
      {
         assert(bits[i]);
      }
   }

   for (SInt32 i = 0; i < _num_cores; i++)
   {
      send_vec.push_back(send_matrix[i][core_id]);
      receive_vec.push_back(receive_matrix[i][core_id]);
   }
}

void bitComplementTrafficGenerator(int core_id, vector<core_id_t>& send_vec, vector<core_id_t>& receive_vec)
{
   assert(isPower2(_num_cores));
   int mask = _num_cores-1;
   int dst_core = (~core_id) & mask;
   send_vec.push_back(dst_core);
   receive_vec.push_back(dst_core);
}

void shuffleTrafficGenerator(int core_id, vector<core_id_t>& send_vec, vector<core_id_t>& receive_vec)
{
   assert(isPower2(_num_cores));
   int mask = _num_cores-1;
   int nbits = floorLog2(_num_cores);
   int dst_core = ((core_id >> (nbits-1)) & 1) | ((core_id << 1) & mask);
   send_vec.push_back(dst_core);
   receive_vec.push_back(dst_core);
}

void transposeTrafficGenerator(int core_id, vector<core_id_t>& send_vec, vector<core_id_t>& receive_vec)
{
   int mesh_width, mesh_height;
   computeEMeshTopologyParams(_num_cores, mesh_width, mesh_height);
   int sx, sy;
   computeEMeshPosition(core_id, sx, sy, mesh_width);
   int dst_core = computeCoreId(sy, sx, mesh_width);

   send_vec.push_back(dst_core);
   receive_vec.push_back(dst_core);
}

void tornadoTrafficGenerator(int core_id, vector<core_id_t>& send_vec, vector<core_id_t>& receive_vec)
{
   int mesh_width, mesh_height;
   computeEMeshTopologyParams(_num_cores, mesh_width, mesh_height);
   int sx, sy;
   computeEMeshPosition(core_id, sx, sy, mesh_width);
   int dst_core = computeCoreId((sx + mesh_width/2) % mesh_width, (sy + mesh_height/2) % mesh_height, mesh_width);

   send_vec.push_back(dst_core);
   receive_vec.push_back(dst_core);
}

void nearestNeighborTrafficGenerator(int core_id, vector<core_id_t>& send_vec, vector<core_id_t>& receive_vec)
{
   int mesh_width, mesh_height;
   computeEMeshTopologyParams(_num_cores, mesh_width, mesh_height);
   int sx, sy;
   computeEMeshPosition(core_id, sx, sy, mesh_width);
   int dst_core = computeCoreId((sx+1) % mesh_width, (sy+1) % mesh_height, mesh_width);

   send_vec.push_back(dst_core);
   receive_vec.push_back(dst_core);
}

void computeEMeshTopologyParams(int num_cores, int& mesh_width, int& mesh_height)
{
   mesh_width = (int) sqrt((float) num_cores);
   mesh_height = (int) ceil(1.0 * num_cores / mesh_width);
   assert(num_cores == (mesh_width * mesh_height));
}

void computeEMeshPosition(int core_id, int& sx, int& sy, int mesh_width)
{
   sx = core_id % mesh_width;
   sy = core_id / mesh_width;
}

int computeCoreId(int sx, int sy, int mesh_width)
{
   return ((sy * mesh_width) + sx);
}
<|endoftext|>


<commit_before>//===- llvm/CodeGen/GlobalISel/InstructionSelect.cpp - InstructionSelect ---==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This file implements the InstructionSelect class.
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetSubtargetInfo.h"

#define DEBUG_TYPE "instruction-select"

using namespace llvm;

char InstructionSelect::ID = 0;
INITIALIZE_PASS_BEGIN(InstructionSelect, DEBUG_TYPE,
                      "Select target instructions out of generic instructions",
                      false, false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_END(InstructionSelect, DEBUG_TYPE,
                    "Select target instructions out of generic instructions",
                    false, false)

InstructionSelect::InstructionSelect() : MachineFunctionPass(ID) {
  initializeInstructionSelectPass(*PassRegistry::getPassRegistry());
}

void InstructionSelect::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<TargetPassConfig>();
  MachineFunctionPass::getAnalysisUsage(AU);
}

static void reportSelectionError(const MachineFunction &MF,
                                 const MachineInstr *MI, const Twine &Message) {
  std::string ErrStorage;
  raw_string_ostream Err(ErrStorage);
  Err << Message << ":\nIn function: " << MF.getName() << '\n';
  if (MI)
    Err << *MI << '\n';
  report_fatal_error(Err.str());
}

bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
  // If the ISel pipeline failed, do not bother running that pass.
  if (MF.getProperties().hasProperty(
          MachineFunctionProperties::Property::FailedISel))
    return false;

  DEBUG(dbgs() << "Selecting function: " << MF.getName() << '\n');

  const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
  const InstructionSelector *ISel = MF.getSubtarget().getInstructionSelector();
  assert(ISel && "Cannot work without InstructionSelector");

  // FIXME: freezeReservedRegs is now done in IRTranslator, but there are many
  // other MF/MFI fields we need to initialize.

  const MachineRegisterInfo &MRI = MF.getRegInfo();

#ifndef NDEBUG
  // Check that our input is fully legal: we require the function to have the
  // Legalized property, so it should be.
  // FIXME: This should be in the MachineVerifier, but it can't use the
  // LegalizerInfo as it's currently in the separate GlobalISel library.
  // The RegBankSelected property is already checked in the verifier. Note
  // that it has the same layering problem, but we only use inline methods so
  // end up not needing to link against the GlobalISel library.
  if (const LegalizerInfo *MLI = MF.getSubtarget().getLegalizerInfo())
    for (const MachineBasicBlock &MBB : MF)
      for (const MachineInstr &MI : MBB)
        if (isPreISelGenericOpcode(MI.getOpcode()) && !MLI->isLegal(MI, MRI))
          reportSelectionError(MF, &MI, "Instruction is not legal");

#endif
  // FIXME: We could introduce new blocks and will need to fix the outer loop.
  // Until then, keep track of the number of blocks to assert that we don't.
  const size_t NumBlocks = MF.size();

  bool Failed = false;
  for (MachineBasicBlock *MBB : post_order(&MF)) {
    if (MBB->empty())
      continue;

    // Select instructions in reverse block order. We permit erasing so have
    // to resort to manually iterating and recognizing the begin (rend) case.
    bool ReachedBegin = false;
    for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
         !ReachedBegin;) {
#ifndef NDEBUG
      // Keep track of the insertion range for debug printing.
      const auto AfterIt = std::next(MII);
#endif
      // Select this instruction.
      MachineInstr &MI = *MII;

      // And have our iterator point to the next instruction, if there is one.
      if (MII == Begin)
        ReachedBegin = true;
      else
        --MII;

      DEBUG(dbgs() << "Selecting: \n  " << MI);

      if (!ISel->select(MI)) {
        if (TPC.isGlobalISelAbortEnabled())
          // FIXME: It would be nice to dump all inserted instructions.  It's
          // not obvious how, esp. considering select() can insert after MI.
          reportSelectionError(MF, &MI, "Cannot select");
        Failed = true;
        break;
      }

      // Dump the range of instructions that MI expanded into.
      DEBUG({
        auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII);
        dbgs() << "Into:\n";
        for (auto &InsertedMI : make_range(InsertedBegin, AfterIt))
          dbgs() << "  " << InsertedMI;
        dbgs() << '\n';
      });
    }
  }

  // Now that selection is complete, there are no more generic vregs.  Verify
  // that the size of the now-constrained vreg is unchanged and that it has a
  // register class.
  for (auto &VRegToType : MRI.getVRegToType()) {
    unsigned VReg = VRegToType.first;
    auto *RC = MRI.getRegClassOrNull(VReg);
    MachineInstr *MI = nullptr;
    if (MRI.def_instr_begin(VReg) != MRI.def_instr_end())
      MI = &*MRI.def_instr_begin(VReg);
    else if (MRI.use_instr_begin(VReg) != MRI.use_instr_end())
      MI = &*MRI.use_instr_begin(VReg);

    if (MI && !RC) {
      if (TPC.isGlobalISelAbortEnabled())
        reportSelectionError(MF, MI, "VReg has no regclass after selection");
      Failed = true;
      break;
    } else if (!RC)
      continue;

    if (VRegToType.second.isValid() &&
        VRegToType.second.getSizeInBits() > (RC->getSize() * 8)) {
      if (TPC.isGlobalISelAbortEnabled())
        reportSelectionError(
            MF, MI, "VReg has explicit size different from class size");
      Failed = true;
      break;
    }
  }

  MRI.getVRegToType().clear();

  if (!TPC.isGlobalISelAbortEnabled() && (Failed || MF.size() != NumBlocks)) {
    MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
    return false;
  }
  assert(MF.size() == NumBlocks && "Inserting blocks is not supported yet");

  // FIXME: Should we accurately track changes?
  return true;
}
<commit_msg>GlobalISel: tidy up def/use test. NFC.<commit_after>//===- llvm/CodeGen/GlobalISel/InstructionSelect.cpp - InstructionSelect ---==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This file implements the InstructionSelect class.
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetSubtargetInfo.h"

#define DEBUG_TYPE "instruction-select"

using namespace llvm;

char InstructionSelect::ID = 0;
INITIALIZE_PASS_BEGIN(InstructionSelect, DEBUG_TYPE,
                      "Select target instructions out of generic instructions",
                      false, false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_END(InstructionSelect, DEBUG_TYPE,
                    "Select target instructions out of generic instructions",
                    false, false)

InstructionSelect::InstructionSelect() : MachineFunctionPass(ID) {
  initializeInstructionSelectPass(*PassRegistry::getPassRegistry());
}

void InstructionSelect::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<TargetPassConfig>();
  MachineFunctionPass::getAnalysisUsage(AU);
}

static void reportSelectionError(const MachineFunction &MF,
                                 const MachineInstr *MI, const Twine &Message) {
  std::string ErrStorage;
  raw_string_ostream Err(ErrStorage);
  Err << Message << ":\nIn function: " << MF.getName() << '\n';
  if (MI)
    Err << *MI << '\n';
  report_fatal_error(Err.str());
}

bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
  // If the ISel pipeline failed, do not bother running that pass.
  if (MF.getProperties().hasProperty(
          MachineFunctionProperties::Property::FailedISel))
    return false;

  DEBUG(dbgs() << "Selecting function: " << MF.getName() << '\n');

  const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
  const InstructionSelector *ISel = MF.getSubtarget().getInstructionSelector();
  assert(ISel && "Cannot work without InstructionSelector");

  // FIXME: freezeReservedRegs is now done in IRTranslator, but there are many
  // other MF/MFI fields we need to initialize.

  const MachineRegisterInfo &MRI = MF.getRegInfo();

#ifndef NDEBUG
  // Check that our input is fully legal: we require the function to have the
  // Legalized property, so it should be.
  // FIXME: This should be in the MachineVerifier, but it can't use the
  // LegalizerInfo as it's currently in the separate GlobalISel library.
  // The RegBankSelected property is already checked in the verifier. Note
  // that it has the same layering problem, but we only use inline methods so
  // end up not needing to link against the GlobalISel library.
  if (const LegalizerInfo *MLI = MF.getSubtarget().getLegalizerInfo())
    for (const MachineBasicBlock &MBB : MF)
      for (const MachineInstr &MI : MBB)
        if (isPreISelGenericOpcode(MI.getOpcode()) && !MLI->isLegal(MI, MRI))
          reportSelectionError(MF, &MI, "Instruction is not legal");

#endif
  // FIXME: We could introduce new blocks and will need to fix the outer loop.
  // Until then, keep track of the number of blocks to assert that we don't.
  const size_t NumBlocks = MF.size();

  bool Failed = false;
  for (MachineBasicBlock *MBB : post_order(&MF)) {
    if (MBB->empty())
      continue;

    // Select instructions in reverse block order. We permit erasing so have
    // to resort to manually iterating and recognizing the begin (rend) case.
    bool ReachedBegin = false;
    for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
         !ReachedBegin;) {
#ifndef NDEBUG
      // Keep track of the insertion range for debug printing.
      const auto AfterIt = std::next(MII);
#endif
      // Select this instruction.
      MachineInstr &MI = *MII;

      // And have our iterator point to the next instruction, if there is one.
      if (MII == Begin)
        ReachedBegin = true;
      else
        --MII;

      DEBUG(dbgs() << "Selecting: \n  " << MI);

      if (!ISel->select(MI)) {
        if (TPC.isGlobalISelAbortEnabled())
          // FIXME: It would be nice to dump all inserted instructions.  It's
          // not obvious how, esp. considering select() can insert after MI.
          reportSelectionError(MF, &MI, "Cannot select");
        Failed = true;
        break;
      }

      // Dump the range of instructions that MI expanded into.
      DEBUG({
        auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII);
        dbgs() << "Into:\n";
        for (auto &InsertedMI : make_range(InsertedBegin, AfterIt))
          dbgs() << "  " << InsertedMI;
        dbgs() << '\n';
      });
    }
  }

  // Now that selection is complete, there are no more generic vregs.  Verify
  // that the size of the now-constrained vreg is unchanged and that it has a
  // register class.
  for (auto &VRegToType : MRI.getVRegToType()) {
    unsigned VReg = VRegToType.first;
    auto *RC = MRI.getRegClassOrNull(VReg);
    MachineInstr *MI = nullptr;
    if (!MRI.def_empty(VReg))
      MI = &*MRI.def_instr_begin(VReg);
    else if (!MRI.use_empty(VReg))
      MI = &*MRI.use_instr_begin(VReg);

    if (MI && !RC) {
      if (TPC.isGlobalISelAbortEnabled())
        reportSelectionError(MF, MI, "VReg has no regclass after selection");
      Failed = true;
      break;
    } else if (!RC)
      continue;

    if (VRegToType.second.isValid() &&
        VRegToType.second.getSizeInBits() > (RC->getSize() * 8)) {
      if (TPC.isGlobalISelAbortEnabled())
        reportSelectionError(
            MF, MI, "VReg has explicit size different from class size");
      Failed = true;
      break;
    }
  }

  MRI.getVRegToType().clear();

  if (!TPC.isGlobalISelAbortEnabled() && (Failed || MF.size() != NumBlocks)) {
    MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
    return false;
  }
  assert(MF.size() == NumBlocks && "Inserting blocks is not supported yet");

  // FIXME: Should we accurately track changes?
  return true;
}
<|endoftext|>