<commit_before>#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
	// Global settings.
	ofSetWindowTitle("Presenter");
	ofSetVerticalSync(true);
	ofEnableSmoothing();
	ofSetFrameRate(60);

	// Position the window in the centre of the screen.
	ofSetWindowPosition((ofGetScreenWidth() - ofGetWindowWidth()) / 2, (ofGetScreenHeight() - ofGetWindowHeight()) / 2);

	// Set status to Welcome screen.
	status = PRESENTER_STATUS_WELCOME;

	// Load logo for welcome screen.
	logo.loadImage("logo.png");
	if(logo.getWidth()>550){
		logo.resize(550, logo.getHeight() / logo.getWidth() * 550);
	}

	// Create presentation chooser buttons.
	gui = new ofxUICanvas();
	gui->setPosition(650, 250);
	gui->setDrawBack(false);

	// Setup custom theme for GUI.
	ofxUIColor cb = ofxUIColor(38, 147, 255, 200);
    ofxUIColor co = ofxUIColor(38, 147, 255, 255);
    ofxUIColor coh = OFX_UI_COLOR_OUTLINE_HIGHLIGHT;
    ofxUIColor cf = ofxUIColor(255, 255, 255, 255);
    ofxUIColor cfh = OFX_UI_COLOR_FILL_HIGHLIGHT;
    ofxUIColor cp = ofxUIColor(38, 147, 255, 255);
    ofxUIColor cpo = OFX_UI_COLOR_PADDED_OUTLINE;
    gui->setUIColors( cb, co, coh, cf, cfh, cp, cpo );

	gui->addLabel("Select a presentation:", OFX_UI_FONT_MEDIUM)->setColorFill(ofxUIColor(0, 0, 0, 255));
    gui->addSpacer();

	// Each directory in bin/data/Presentations is concidered a presentation.
	int i, size;
	ofDirectory presentations;
	presentations = ofDirectory("Presentations");
	presentations.listDir();
	presentations.sort();
	size = presentations.size();

	activeButton = 0;
	for (i = 0; i < size; i++){
		if (presentations.getFile(i).isDirectory()==1){
			ofxUILabelButton *btn = gui->addLabelButton(presentations.getFile(i).getFileName(), false, 300, 30, 0, 0, true);
			btn->setPadding(5);
			btn->setDrawPaddingOutline(true);
			if(i==0){
				btn->setColorPaddedOutline(ofxUIColor(38, 147, 255, 255));
			}
			buttons.push_back(btn);
		}
	}

    gui->autoSizeToFitWidgets();
    ofAddListener(gui->newGUIEvent,this,&ofApp::guiEvent);

	// Create shutdown button.
	shutdown = new ofxUICanvas();
	shutdown->setPosition(ofGetWindowWidth()-60, 10);
	shutdown->setDrawBack(false);

	shutdown->setGlobalButtonDimension(44);
	shutdown->addImageButton("Shutdown", "shutdown.png", false);
	shutdown->autoSizeToFitWidgets();
    ofAddListener(shutdown->newGUIEvent,this,&ofApp::guiEvent);

#if defined(TARGET_RASPBERRY_PI)
	ofHideCursor();
#endif

}

//--------------------------------------------------------------
void ofApp::update(){
	if(status == PRESENTER_STATUS_WELCOME){

	} else if (status == PRESENTER_STATUS_PRESENTATION){
		if(presentation != NULL){
			presentation->update();
		}
	}
}

//--------------------------------------------------------------
void ofApp::draw(){
	if(status == PRESENTER_STATUS_WELCOME){
		ofBackground(ofColor::white);
		logo.draw(50,75);
	} else if (status == PRESENTER_STATUS_PRESENTATION){
		if(presentation != NULL){
			presentation->draw();
		}
	}
}

void ofApp::guiEvent(ofxUIEventArgs &e)
{
	string name = e.widget->getName();
	int kind = e.widget->getKind();

    if(kind == OFX_UI_WIDGET_LABELBUTTON)
    {
        ofxUIButton *button = (ofxUIButton *) e.widget;
		if(!button->getValue()){
			loadPresentation(name);
		}
    }
    else if(kind == OFX_UI_WIDGET_IMAGEBUTTON)
    {
        ofxUIImageButton *button = (ofxUIImageButton *) e.widget;
        if(button->getValue()){

#if defined(TARGET_RASPBERRY_PI)
			// On Raspberry Pi, shutdown.
			std::system("sudo shutdown -h now");
#else
			// Desktop applications, close the application.
			std::exit(0);
#endif

		}
    }
}

//--------------------------------------------------------------
void ofApp::exit()
{
    delete gui;
}

void ofApp::endPresentation(){
	status = PRESENTER_STATUS_WELCOME;
#if !defined(TARGET_RASPBERRY_PI)
	ofShowCursor();
#endif
	gui->setVisible(true);
	shutdown->setVisible(true);
	delete presentation;
	presentation = NULL;
}

void ofApp::loadPresentation(string name){
	// load presentation xml file.
	presentation = new Presentation(name);

	// set the status and hide the gui on welcome screen.
	status = PRESENTER_STATUS_PRESENTATION;
#if !defined(TARGET_RASPBERRY_PI)
	ofHideCursor();
#endif
	gui->setVisible(false);
	shutdown->setVisible(false);

	cout << name << endl;
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key)
{
	cout << "KEY: " << ofToString(key) << endl;

    switch (key)
    {
        case 'g':
            gui->toggleVisible();
			break;
		case 'x':
			if (status == PRESENTER_STATUS_PRESENTATION){
				presentation->exit();
				endPresentation();
			}
			break;
		case OF_KEY_RIGHT:
			if (status == PRESENTER_STATUS_PRESENTATION){
				if(presentation->next()==0){
					endPresentation();
				}
			}
            break;
		case OF_KEY_LEFT:
			if (status == PRESENTER_STATUS_PRESENTATION){
				if(presentation->previous()==0){
					endPresentation();
				}
			}
            break;
		case OF_KEY_UP:
			if (status == PRESENTER_STATUS_WELCOME){
				int prevButton = activeButton;
				if(--activeButton == -1){
					activeButton = buttons.size() - 1;
				}

				ofxUILabelButton* btn = buttons[prevButton];
				btn->setColorPaddedOutline(ofxUIColor(255, 255, 255, 255));

				btn = buttons[activeButton];
				btn->setColorPaddedOutline(ofxUIColor(38, 147, 255, 255));
			}
            break;
		case OF_KEY_DOWN:
			if (status == PRESENTER_STATUS_WELCOME){
				int prevButton = activeButton;
				if(++activeButton == buttons.size()){
					activeButton = 0;
				}

				ofxUILabelButton* btn = buttons[prevButton];
				btn->setColorPaddedOutline(ofxUIColor(255, 255, 255, 255));

				btn = buttons[activeButton];
				btn->setColorPaddedOutline(ofxUIColor(38, 147, 255, 255));
			}
            break;
		case OF_KEY_RETURN:
		case 10: //somehow the RETURN key on RPi is 10 and not OF_KEY_RETURN
			if (status == PRESENTER_STATUS_WELCOME){
				ofxUILabelButton* btn = buttons[activeButton];
				loadPresentation(btn->getName());
			}
			break;
        default:
            break;
    }
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
	switch (button)
    {
		case OF_MOUSE_BUTTON_RIGHT:
			if (status == PRESENTER_STATUS_PRESENTATION){
				if(presentation->next()==0){
					endPresentation();
				}
			}
            break;
		case OF_MOUSE_BUTTON_LEFT:
			if (status == PRESENTER_STATUS_PRESENTATION){
				if(presentation->previous()==0){
					endPresentation();
				}
			}
            break;
        default:
            break;
    }
}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<commit_msg>Release 1.0.0<commit_after>#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
	// Global settings.
	ofSetWindowTitle("Presenter");
	ofSetVerticalSync(true);
	ofEnableSmoothing();
	ofSetFrameRate(60);

	// Position the window in the centre of the screen.
	ofSetWindowPosition((ofGetScreenWidth() - ofGetWindowWidth()) / 2, (ofGetScreenHeight() - ofGetWindowHeight()) / 2);

	// Set status to Welcome screen.
	status = PRESENTER_STATUS_WELCOME;

	// Load logo for welcome screen.
	logo.loadImage("logo.png");
	if(logo.getWidth()>550){
		logo.resize(550, logo.getHeight() / logo.getWidth() * 550);
	}

	// Create presentation chooser buttons.
	gui = new ofxUICanvas();
	gui->setPosition(650, 250);
	gui->setDrawBack(false);

	// Setup custom theme for GUI.
	ofxUIColor cb = ofxUIColor(38, 147, 255, 200);
    ofxUIColor co = ofxUIColor(38, 147, 255, 255);
    ofxUIColor coh = OFX_UI_COLOR_OUTLINE_HIGHLIGHT;
    ofxUIColor cf = ofxUIColor(255, 255, 255, 255);
    ofxUIColor cfh = OFX_UI_COLOR_FILL_HIGHLIGHT;
    ofxUIColor cp = ofxUIColor(38, 147, 255, 255);
    ofxUIColor cpo = OFX_UI_COLOR_PADDED_OUTLINE;
    gui->setUIColors( cb, co, coh, cf, cfh, cp, cpo );

	gui->addLabel("Select a presentation:", OFX_UI_FONT_MEDIUM)->setColorFill(ofxUIColor(0, 0, 0, 255));
    gui->addSpacer();

	// Each directory in bin/data/Presentations is concidered a presentation.
	int i, size;
	ofDirectory presentations;
	presentations = ofDirectory("Presentations");
	presentations.listDir();
	presentations.sort();
	size = presentations.size();

	activeButton = 0;
	for (i = 0; i < size; i++){
		if (presentations.getFile(i).isDirectory()==1){
			ofxUILabelButton *btn = gui->addLabelButton(presentations.getFile(i).getFileName(), false, 300, 30, 0, 0, true);
			btn->setPadding(5);
			btn->setDrawPaddingOutline(true);
			if(i==0){
				btn->setColorPaddedOutline(ofxUIColor(38, 147, 255, 255));
			}
			buttons.push_back(btn);
		}
	}

    gui->autoSizeToFitWidgets();
    ofAddListener(gui->newGUIEvent,this,&ofApp::guiEvent);

	// Create shutdown button.
	shutdown = new ofxUICanvas();
	shutdown->setPosition(ofGetWindowWidth()-60, 10);
	shutdown->setDrawBack(false);

	shutdown->setGlobalButtonDimension(44);
	shutdown->addImageButton("Shutdown", "shutdown.png", false);
	shutdown->autoSizeToFitWidgets();
    ofAddListener(shutdown->newGUIEvent,this,&ofApp::guiEvent);

#if defined(TARGET_RASPBERRY_PI)
	ofHideCursor();
#endif

}

//--------------------------------------------------------------
void ofApp::update(){
	if(status == PRESENTER_STATUS_WELCOME){

	} else if (status == PRESENTER_STATUS_PRESENTATION){
		if(presentation != NULL){
			presentation->update();
		}
	}
}

//--------------------------------------------------------------
void ofApp::draw(){
	if(status == PRESENTER_STATUS_WELCOME){
		// White background
		ofSetColor(ofColor::white);
		ofBackground(ofColor::white);

		// LUKE Theatre Group logo
		logo.draw(50,75);

		// Presenter version
		ofSetColor(ofColor(ofColor::dimGrey));
		ofDrawBitmapString("1.0.0", 960, 740);
	} else if (status == PRESENTER_STATUS_PRESENTATION){
		if(presentation != NULL){
			presentation->draw();
		}
	}
}

void ofApp::guiEvent(ofxUIEventArgs &e)
{
	string name = e.widget->getName();
	int kind = e.widget->getKind();

    if(kind == OFX_UI_WIDGET_LABELBUTTON)
    {
        ofxUIButton *button = (ofxUIButton *) e.widget;
		if(!button->getValue()){
			loadPresentation(name);
		}
    }
    else if(kind == OFX_UI_WIDGET_IMAGEBUTTON)
    {
        ofxUIImageButton *button = (ofxUIImageButton *) e.widget;
        if(button->getValue()){

#if defined(TARGET_RASPBERRY_PI)
			// On Raspberry Pi, shutdown.
			std::system("sudo shutdown -h now");
#else
			// Desktop applications, close the application.
			std::exit(0);
#endif

		}
    }
}

//--------------------------------------------------------------
void ofApp::exit()
{
    delete gui;
}

void ofApp::endPresentation(){
	status = PRESENTER_STATUS_WELCOME;
#if !defined(TARGET_RASPBERRY_PI)
	ofShowCursor();
#endif
	gui->setVisible(true);
	shutdown->setVisible(true);
	delete presentation;
	presentation = NULL;
}

void ofApp::loadPresentation(string name){
	// load presentation xml file.
	presentation = new Presentation(name);

	// set the status and hide the gui on welcome screen.
	status = PRESENTER_STATUS_PRESENTATION;
#if !defined(TARGET_RASPBERRY_PI)
	ofHideCursor();
#endif
	gui->setVisible(false);
	shutdown->setVisible(false);

	cout << name << endl;
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key)
{
	cout << "KEY: " << ofToString(key) << endl;

    switch (key)
    {
        case 'g':
            gui->toggleVisible();
			break;
		case 'x':
			if (status == PRESENTER_STATUS_PRESENTATION){
				presentation->exit();
				endPresentation();
			}
			break;
		case OF_KEY_RIGHT:
			if (status == PRESENTER_STATUS_PRESENTATION){
				if(presentation->next()==0){
					endPresentation();
				}
			}
            break;
		case OF_KEY_LEFT:
			if (status == PRESENTER_STATUS_PRESENTATION){
				if(presentation->previous()==0){
					endPresentation();
				}
			}
            break;
		case OF_KEY_UP:
			if (status == PRESENTER_STATUS_WELCOME){
				int prevButton = activeButton;
				if(--activeButton == -1){
					activeButton = buttons.size() - 1;
				}

				ofxUILabelButton* btn = buttons[prevButton];
				btn->setColorPaddedOutline(ofxUIColor(255, 255, 255, 255));

				btn = buttons[activeButton];
				btn->setColorPaddedOutline(ofxUIColor(38, 147, 255, 255));
			}
            break;
		case OF_KEY_DOWN:
			if (status == PRESENTER_STATUS_WELCOME){
				int prevButton = activeButton;
				if(++activeButton == buttons.size()){
					activeButton = 0;
				}

				ofxUILabelButton* btn = buttons[prevButton];
				btn->setColorPaddedOutline(ofxUIColor(255, 255, 255, 255));

				btn = buttons[activeButton];
				btn->setColorPaddedOutline(ofxUIColor(38, 147, 255, 255));
			}
            break;
		case OF_KEY_RETURN:
		case 10: //somehow the RETURN key on RPi is 10 and not OF_KEY_RETURN
			if (status == PRESENTER_STATUS_WELCOME){
				ofxUILabelButton* btn = buttons[activeButton];
				loadPresentation(btn->getName());
			}
			break;
        default:
            break;
    }
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
	switch (button)
    {
		case OF_MOUSE_BUTTON_RIGHT:
			if (status == PRESENTER_STATUS_PRESENTATION){
				if(presentation->next()==0){
					endPresentation();
				}
			}
            break;
		case OF_MOUSE_BUTTON_LEFT:
			if (status == PRESENTER_STATUS_PRESENTATION){
				if(presentation->previous()==0){
					endPresentation();
				}
			}
            break;
        default:
            break;
    }
}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<|endoftext|>


<commit_before>///
/// @file  imath.hpp
/// @brief Integer math functions used in primecount
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef IMATH_HPP
#define IMATH_HPP

#include <isqrt.hpp>

#include <stdint.h>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <vector>

namespace {

inline int64_t isquare(int64_t x)
{
  return x * x;
}

template <typename A, typename B>
inline A ceil_div(A a, B b)
{
  assert(b > 0);
  return (A) ((a + b - 1) / b);
}

template <typename T>
inline T number_of_bits(T)
{
  return (T) (sizeof(T) * 8);
}

template <typename T>
inline bool is_power_of_2(T x)
{
  return (x != 0 && (x & (x - 1)) == 0);
}

template <typename T>
inline T next_power_of_2(T x)
{
  if (x == 0)
    return 1;

  x--;
  for (T i = 1; i < number_of_bits(x); i += i)
    x |= (x >> i);

  return ++x;
}

template <typename T>
inline T prev_power_of_2(T x)
{
  for (T i = 1; i < number_of_bits(x); i += i)
    x |= (x >> i);

  return x - (x >> 1);
}

template <typename T>
inline int ilog(T x)
{
  return (int) std::log((double) x);
}

template <typename T>
inline T ipow(T x, int n)
{
  T r = 1;
  for (int i = 0; i < n; i++)
    r *= x;

  return r;
}

/// Check if ipow(x, n) <= limit
template <typename T>
inline bool ipow_less_equal(T x, int n, T limit)
{
  if (limit <= 0)
    return false;

  for (T r = 1; n > 0; n--, r *= x)
    if (r > limit / x)
      return false;

  return true;
}

/// Integer nth root
template <int N, typename T>
inline T iroot(T x)
{
  T r = (T) std::pow((double) x, 1.0 / N);

  while (ipow(r, N) > x)
    r--;
  while (ipow_less_equal(r + 1, N, x))
    r++;

  return r;
}

/// Count the number of primes <= x using binary search.
/// @pre primes[1] = 2, primes[3] = 3, ...
/// @pre x <= primes.back()
///
template <typename T1, typename T2>
inline T2 pi_bsearch(const std::vector<T1>& primes, T2 x)
{
  assert(primes[0] == 0);
  return (T2) (std::upper_bound(primes.begin() + 1, primes.end(), x) - (primes.begin() + 1));
}

/// Count the number of primes <= x using binary search.
/// @pre primes[1] = 2, primes[3] = 3, ...
/// @pre x <= primes.back()
///
template <typename T1, typename T2, typename T3>
inline T3 pi_bsearch(const std::vector<T1>& primes, T2 len, T3 x)
{
  assert(primes[0] == 0);
  return (T3) (std::upper_bound(primes.begin() + 1, primes.begin() + len + 1, x) - (primes.begin() + 1));
}

template <typename T1, typename T2, typename T3>
inline T2 in_between(T1 min, T2 x, T3 max)
{
  if (x < min)
    return (T2) min;
  if (x > max)
    return (T2) max;

  return x;
}

} // namespace

#endif
<commit_msg>Remove unused function<commit_after>///
/// @file  imath.hpp
/// @brief Integer math functions used in primecount
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef IMATH_HPP
#define IMATH_HPP

#include <isqrt.hpp>

#include <stdint.h>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <vector>

namespace {

inline int64_t isquare(int64_t x)
{
  return x * x;
}

template <typename A, typename B>
inline A ceil_div(A a, B b)
{
  assert(b > 0);
  return (A) ((a + b - 1) / b);
}

template <typename T>
inline T number_of_bits(T)
{
  return (T) (sizeof(T) * 8);
}

template <typename T>
inline bool is_power_of_2(T x)
{
  return (x != 0 && (x & (x - 1)) == 0);
}

template <typename T>
inline T next_power_of_2(T x)
{
  if (x == 0)
    return 1;

  x--;
  for (T i = 1; i < number_of_bits(x); i += i)
    x |= (x >> i);

  return ++x;
}

template <typename T>
inline T prev_power_of_2(T x)
{
  for (T i = 1; i < number_of_bits(x); i += i)
    x |= (x >> i);

  return x - (x >> 1);
}

template <typename T>
inline int ilog(T x)
{
  return (int) std::log((double) x);
}

template <typename T>
inline T ipow(T x, int n)
{
  T r = 1;
  for (int i = 0; i < n; i++)
    r *= x;

  return r;
}

/// Check if ipow(x, n) <= limit
template <typename T>
inline bool ipow_less_equal(T x, int n, T limit)
{
  if (limit <= 0)
    return false;

  for (T r = 1; n > 0; n--, r *= x)
    if (r > limit / x)
      return false;

  return true;
}

/// Integer nth root
template <int N, typename T>
inline T iroot(T x)
{
  T r = (T) std::pow((double) x, 1.0 / N);

  while (ipow(r, N) > x)
    r--;
  while (ipow_less_equal(r + 1, N, x))
    r++;

  return r;
}

/// Count the number of primes <= x using binary search.
/// @pre primes[1] = 2, primes[3] = 3, ...
/// @pre x <= primes.back()
///
template <typename T1, typename T2>
inline T2 pi_bsearch(const std::vector<T1>& primes, T2 x)
{
  assert(primes[0] == 0);
  return (T2) (std::upper_bound(primes.begin() + 1, primes.end(), x) - (primes.begin() + 1));
}

template <typename T1, typename T2, typename T3>
inline T2 in_between(T1 min, T2 x, T3 max)
{
  if (x < min)
    return (T2) min;
  if (x > max)
    return (T2) max;

  return x;
}

} // namespace

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2009 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 <config.h>

// When defined, different heap allocators can be used via an environment
// variable set before running the program.  This may reduce the amount
// of inlining that we get with malloc/free/etc.  Disabling makes it
// so that only tcmalloc can be used.
#define ENABLE_DYNAMIC_ALLOCATOR_SWITCHING

// TODO(mbelshe): Ensure that all calls to tcmalloc have the proper call depth
// from the "user code" so that debugging tools (HeapChecker) can work.

// __THROW is defined in glibc systems.  It means, counter-intuitively,
// "This function will never throw an exception."  It's an optional
// optimization tool, but we may need to use it to match glibc prototypes.
#ifndef __THROW    // I guess we're not on a glibc system
# define __THROW   // __THROW is just an optimization, so ok to make it ""
#endif

// new_mode behaves similarly to MSVC's _set_new_mode.
// If flag is 0 (default), calls to malloc will behave normally.
// If flag is 1, calls to malloc will behave like calls to new,
// and the std_new_handler will be invoked on failure.
// Can be set by calling _set_new_mode().
static int new_mode = 0;

typedef enum {
  TCMALLOC,    // TCMalloc is the default allocator.
  JEMALLOC,    // JEMalloc
  WINDEFAULT,  // Windows Heap
  WINLFH,      // Windows LFH Heap
} Allocator;

// This is the default allocator.
static Allocator allocator = WINDEFAULT;

// We include tcmalloc and the win_allocator to get as much inlining as
// possible.
#include "tcmalloc.cc"
#include "win_allocator.cc"

// Forward declarations from jemalloc.
extern "C" {
void* je_malloc(size_t s);
void* je_realloc(void* p, size_t s);
void je_free(void* s);
size_t je_msize(void* p);
bool je_malloc_init_hard();
}

extern "C" {

// Call the new handler, if one has been set.
// Returns true on successfully calling the handler, false otherwise.
inline bool call_new_handler(bool nothrow) {
  // Get the current new handler.  NB: this function is not
  // thread-safe.  We make a feeble stab at making it so here, but
  // this lock only protects against tcmalloc interfering with
  // itself, not with other libraries calling set_new_handler.
  std::new_handler nh;
  {
    SpinLockHolder h(&set_new_handler_lock);
    nh = std::set_new_handler(0);
    (void) std::set_new_handler(nh);
  }
#if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
  if (!nh)
    return false;
  // Since exceptions are disabled, we don't really know if new_handler
  // failed.  Assume it will abort if it fails.
  (*nh)();
  return false;  // break out of the retry loop.
#else
  // If no new_handler is established, the allocation failed.
  if (!nh) {
    if (nothrow)
      return 0;
    throw std::bad_alloc();
  }
  // Otherwise, try the new_handler.  If it returns, retry the
  // allocation.  If it throws std::bad_alloc, fail the allocation.
  // if it throws something else, don't interfere.
  try {
    (*nh)();
  } catch (const std::bad_alloc&) {
    if (!nothrow)
      throw;
    return true;
  }
#endif  // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
}

void* malloc(size_t size) __THROW {
  void* ptr;
  for (;;) {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
    switch (allocator) {
      case JEMALLOC:
        ptr = je_malloc(size);
        break;
      case WINDEFAULT:
      case WINLFH:
        ptr = win_heap_malloc(size);
        break;
      case TCMALLOC:
      default:
        ptr = do_malloc(size);
        break;
    }
#else
    // TCMalloc case.
    ptr = do_malloc(size);
#endif
    if (ptr)
      return ptr;

    if (!new_mode || !call_new_handler(true))
      break;
  }
  return ptr;
}

void free(void* p) __THROW {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
  switch (allocator) {
    case JEMALLOC:
      je_free(p);
      return;
    case WINDEFAULT:
    case WINLFH:
      win_heap_free(p);
      return;
  }
#endif
  // TCMalloc case.
  do_free(p);
}

void* realloc(void* ptr, size_t size) __THROW {
  // Webkit is brittle for allocators that return NULL for malloc(0).  The
  // realloc(0, 0) code path does not guarantee a non-NULL return, so be sure
  // to call malloc for this case.
  if (!ptr)
    return malloc(size);

  void* new_ptr;
  for (;;) {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
    switch (allocator) {
      case JEMALLOC:
        new_ptr = je_realloc(ptr, size);
        break;
      case WINDEFAULT:
      case WINLFH:
        new_ptr = win_heap_realloc(ptr, size);
        break;
      case TCMALLOC:
      default:
        new_ptr = do_realloc(ptr, size);
        break;
    }
#else
    // TCMalloc case.
    new_ptr = do_realloc(ptr, size);
#endif

    // Subtle warning:  NULL return does not alwas indicate out-of-memory.  If
    // the requested new size is zero, realloc should free the ptr and return
    // NULL.
    if (new_ptr || !size)
      return new_ptr;
    if (!new_mode || !call_new_handler(true))
      break;
  }
  return new_ptr;
}

// TODO(mbelshe): Implement this for other allocators.
void malloc_stats(void) __THROW {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
  switch (allocator) {
    case JEMALLOC:
      // No stats.
      return;
    case WINDEFAULT:
    case WINLFH:
      // No stats.
      return;
  }
#endif
  tc_malloc_stats();
}

#ifdef WIN32

extern "C" size_t _msize(void* p) {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
  switch (allocator) {
    case JEMALLOC:
      return je_msize(p);
    case WINDEFAULT:
    case WINLFH:
      return win_heap_msize(p);
  }
#endif
  return MallocExtension::instance()->GetAllocatedSize(p);
}

// This is included to resolve references from libcmt.
extern "C" intptr_t _get_heap_handle() {
  return 0;
}

// The CRT heap initialization stub.
extern "C" int _heap_init() {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
  const char* override = GetenvBeforeMain("CHROME_ALLOCATOR");
  if (override) {
    if (!stricmp(override, "jemalloc"))
      allocator = JEMALLOC;
    else if (!stricmp(override, "winheap"))
      allocator = WINDEFAULT;
    else if (!stricmp(override, "winlfh"))
      allocator = WINLFH;
    else if (!stricmp(override, "tcmalloc"))
      allocator = TCMALLOC;
  }

  switch (allocator) {
    case JEMALLOC:
      return je_malloc_init_hard() ? 0 : 1;
    case WINDEFAULT:
      return win_heap_init(false) ? 1 : 0;
    case WINLFH:
      return win_heap_init(true) ? 1 : 0;
    case TCMALLOC:
    default:
      // fall through
      break;
  }
#endif
  // Initializing tcmalloc.
  // We intentionally leak this object.  It lasts for the process
  // lifetime.  Trying to teardown at _heap_term() is so late that
  // you can't do anything useful anyway.
  new TCMallocGuard();
  return 1;
}

// The CRT heap cleanup stub.
extern "C" void _heap_term() {}

// We set this to 1 because part of the CRT uses a check of _crtheap != 0
// to test whether the CRT has been initialized.  Once we've ripped out
// the allocators from libcmt, we need to provide this definition so that
// the rest of the CRT is still usable.
extern "C" void* _crtheap = reinterpret_cast<void*>(1);

#endif  // WIN32

#include "generic_allocators.cc"

}  // extern C
<commit_msg>Revert 77066 - Test impact of using default windows allocator<commit_after>// Copyright (c) 2009 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 <config.h>

// When defined, different heap allocators can be used via an environment
// variable set before running the program.  This may reduce the amount
// of inlining that we get with malloc/free/etc.  Disabling makes it
// so that only tcmalloc can be used.
#define ENABLE_DYNAMIC_ALLOCATOR_SWITCHING

// TODO(mbelshe): Ensure that all calls to tcmalloc have the proper call depth
// from the "user code" so that debugging tools (HeapChecker) can work.

// __THROW is defined in glibc systems.  It means, counter-intuitively,
// "This function will never throw an exception."  It's an optional
// optimization tool, but we may need to use it to match glibc prototypes.
#ifndef __THROW    // I guess we're not on a glibc system
# define __THROW   // __THROW is just an optimization, so ok to make it ""
#endif

// new_mode behaves similarly to MSVC's _set_new_mode.
// If flag is 0 (default), calls to malloc will behave normally.
// If flag is 1, calls to malloc will behave like calls to new,
// and the std_new_handler will be invoked on failure.
// Can be set by calling _set_new_mode().
static int new_mode = 0;

typedef enum {
  TCMALLOC,    // TCMalloc is the default allocator.
  JEMALLOC,    // JEMalloc
  WINDEFAULT,  // Windows Heap
  WINLFH,      // Windows LFH Heap
} Allocator;

// This is the default allocator.
static Allocator allocator = TCMALLOC;

// We include tcmalloc and the win_allocator to get as much inlining as
// possible.
#include "tcmalloc.cc"
#include "win_allocator.cc"

// Forward declarations from jemalloc.
extern "C" {
void* je_malloc(size_t s);
void* je_realloc(void* p, size_t s);
void je_free(void* s);
size_t je_msize(void* p);
bool je_malloc_init_hard();
}

extern "C" {

// Call the new handler, if one has been set.
// Returns true on successfully calling the handler, false otherwise.
inline bool call_new_handler(bool nothrow) {
  // Get the current new handler.  NB: this function is not
  // thread-safe.  We make a feeble stab at making it so here, but
  // this lock only protects against tcmalloc interfering with
  // itself, not with other libraries calling set_new_handler.
  std::new_handler nh;
  {
    SpinLockHolder h(&set_new_handler_lock);
    nh = std::set_new_handler(0);
    (void) std::set_new_handler(nh);
  }
#if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
  if (!nh)
    return false;
  // Since exceptions are disabled, we don't really know if new_handler
  // failed.  Assume it will abort if it fails.
  (*nh)();
  return false;  // break out of the retry loop.
#else
  // If no new_handler is established, the allocation failed.
  if (!nh) {
    if (nothrow)
      return 0;
    throw std::bad_alloc();
  }
  // Otherwise, try the new_handler.  If it returns, retry the
  // allocation.  If it throws std::bad_alloc, fail the allocation.
  // if it throws something else, don't interfere.
  try {
    (*nh)();
  } catch (const std::bad_alloc&) {
    if (!nothrow)
      throw;
    return true;
  }
#endif  // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
}

void* malloc(size_t size) __THROW {
  void* ptr;
  for (;;) {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
    switch (allocator) {
      case JEMALLOC:
        ptr = je_malloc(size);
        break;
      case WINDEFAULT:
      case WINLFH:
        ptr = win_heap_malloc(size);
        break;
      case TCMALLOC:
      default:
        ptr = do_malloc(size);
        break;
    }
#else
    // TCMalloc case.
    ptr = do_malloc(size);
#endif
    if (ptr)
      return ptr;

    if (!new_mode || !call_new_handler(true))
      break;
  }
  return ptr;
}

void free(void* p) __THROW {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
  switch (allocator) {
    case JEMALLOC:
      je_free(p);
      return;
    case WINDEFAULT:
    case WINLFH:
      win_heap_free(p);
      return;
  }
#endif
  // TCMalloc case.
  do_free(p);
}

void* realloc(void* ptr, size_t size) __THROW {
  // Webkit is brittle for allocators that return NULL for malloc(0).  The
  // realloc(0, 0) code path does not guarantee a non-NULL return, so be sure
  // to call malloc for this case.
  if (!ptr)
    return malloc(size);

  void* new_ptr;
  for (;;) {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
    switch (allocator) {
      case JEMALLOC:
        new_ptr = je_realloc(ptr, size);
        break;
      case WINDEFAULT:
      case WINLFH:
        new_ptr = win_heap_realloc(ptr, size);
        break;
      case TCMALLOC:
      default:
        new_ptr = do_realloc(ptr, size);
        break;
    }
#else
    // TCMalloc case.
    new_ptr = do_realloc(ptr, size);
#endif

    // Subtle warning:  NULL return does not alwas indicate out-of-memory.  If
    // the requested new size is zero, realloc should free the ptr and return
    // NULL.
    if (new_ptr || !size)
      return new_ptr;
    if (!new_mode || !call_new_handler(true))
      break;
  }
  return new_ptr;
}

// TODO(mbelshe): Implement this for other allocators.
void malloc_stats(void) __THROW {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
  switch (allocator) {
    case JEMALLOC:
      // No stats.
      return;
    case WINDEFAULT:
    case WINLFH:
      // No stats.
      return;
  }
#endif
  tc_malloc_stats();
}

#ifdef WIN32

extern "C" size_t _msize(void* p) {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
  switch (allocator) {
    case JEMALLOC:
      return je_msize(p);
    case WINDEFAULT:
    case WINLFH:
      return win_heap_msize(p);
  }
#endif
  return MallocExtension::instance()->GetAllocatedSize(p);
}

// This is included to resolve references from libcmt.
extern "C" intptr_t _get_heap_handle() {
  return 0;
}

// The CRT heap initialization stub.
extern "C" int _heap_init() {
#ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
  const char* override = GetenvBeforeMain("CHROME_ALLOCATOR");
  if (override) {
    if (!stricmp(override, "jemalloc"))
      allocator = JEMALLOC;
    else if (!stricmp(override, "winheap"))
      allocator = WINDEFAULT;
    else if (!stricmp(override, "winlfh"))
      allocator = WINLFH;
    else if (!stricmp(override, "tcmalloc"))
      allocator = TCMALLOC;
  }

  switch (allocator) {
    case JEMALLOC:
      return je_malloc_init_hard() ? 0 : 1;
    case WINDEFAULT:
      return win_heap_init(false) ? 1 : 0;
    case WINLFH:
      return win_heap_init(true) ? 1 : 0;
    case TCMALLOC:
    default:
      // fall through
      break;
  }
#endif
  // Initializing tcmalloc.
  // We intentionally leak this object.  It lasts for the process
  // lifetime.  Trying to teardown at _heap_term() is so late that
  // you can't do anything useful anyway.
  new TCMallocGuard();
  return 1;
}

// The CRT heap cleanup stub.
extern "C" void _heap_term() {}

// We set this to 1 because part of the CRT uses a check of _crtheap != 0
// to test whether the CRT has been initialized.  Once we've ripped out
// the allocators from libcmt, we need to provide this definition so that
// the rest of the CRT is still usable.
extern "C" void* _crtheap = reinterpret_cast<void*>(1);

#endif  // WIN32

#include "generic_allocators.cc"

}  // extern C
<|endoftext|>


<commit_before>//===- ARMConstantPoolValue.cpp - ARM constantpool value --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ARM specific constantpool value class.
//
//===----------------------------------------------------------------------===//

#include "ARMConstantPoolValue.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Constant.h"
#include "llvm/Constants.h"
#include "llvm/GlobalValue.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
using namespace llvm;

//===----------------------------------------------------------------------===//
// ARMConstantPoolValue
//===----------------------------------------------------------------------===//

ARMConstantPoolValue::ARMConstantPoolValue(Type *Ty, unsigned id,
                                           ARMCP::ARMCPKind kind,
                                           unsigned char PCAdj,
                                           ARMCP::ARMCPModifier modifier,
                                           bool addCurrentAddress)
  : MachineConstantPoolValue(Ty), LabelId(id), Kind(kind),
    PCAdjust(PCAdj), Modifier(modifier),
    AddCurrentAddress(addCurrentAddress) {}

ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C, unsigned id,
                                           ARMCP::ARMCPKind kind,
                                           unsigned char PCAdj,
                                           ARMCP::ARMCPModifier modifier,
                                           bool addCurrentAddress)
  : MachineConstantPoolValue((Type*)Type::getInt32Ty(C)),
    LabelId(id), Kind(kind), PCAdjust(PCAdj), Modifier(modifier),
    AddCurrentAddress(addCurrentAddress) {}

ARMConstantPoolValue::~ARMConstantPoolValue() {}

const char *ARMConstantPoolValue::getModifierText() const {
  switch (Modifier) {
  default: llvm_unreachable("Unknown modifier!");
    // FIXME: Are these case sensitive? It'd be nice to lower-case all the
    // strings if that's legal.
  case ARMCP::no_modifier: return "none";
  case ARMCP::TLSGD:       return "tlsgd";
  case ARMCP::GOT:         return "GOT";
  case ARMCP::GOTOFF:      return "GOTOFF";
  case ARMCP::GOTTPOFF:    return "gottpoff";
  case ARMCP::TPOFF:       return "tpoff";
  }
}

int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
                                                    unsigned Alignment) {
  assert(false && "Shouldn't be calling this directly!");
  return -1;
}

void
ARMConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
  ID.AddInteger(LabelId);
  ID.AddInteger(PCAdjust);
}

bool
ARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) {
  if (ACPV->Kind == Kind &&
      ACPV->PCAdjust == PCAdjust &&
      ACPV->Modifier == Modifier) {
    if (ACPV->LabelId == LabelId)
      return true;
    // Two PC relative constpool entries containing the same GV address or
    // external symbols. FIXME: What about blockaddress?
    if (Kind == ARMCP::CPValue || Kind == ARMCP::CPExtSymbol)
      return true;
  }
  return false;
}

void ARMConstantPoolValue::dump() const {
  errs() << "  " << *this;
}

void ARMConstantPoolValue::print(raw_ostream &O) const {
  if (Modifier) O << "(" << getModifierText() << ")";
  if (PCAdjust != 0) {
    O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust;
    if (AddCurrentAddress) O << "-.";
    O << ")";
  }
}

//===----------------------------------------------------------------------===//
// ARMConstantPoolConstant
//===----------------------------------------------------------------------===//

ARMConstantPoolConstant::ARMConstantPoolConstant(Type *Ty,
                                                 const Constant *C,
                                                 unsigned ID,
                                                 ARMCP::ARMCPKind Kind,
                                                 unsigned char PCAdj,
                                                 ARMCP::ARMCPModifier Modifier,
                                                 bool AddCurrentAddress)
  : ARMConstantPoolValue(Ty, ID, Kind, PCAdj, Modifier, AddCurrentAddress),
    CVal(C) {}

ARMConstantPoolConstant::ARMConstantPoolConstant(const Constant *C,
                                                 unsigned ID,
                                                 ARMCP::ARMCPKind Kind,
                                                 unsigned char PCAdj,
                                                 ARMCP::ARMCPModifier Modifier,
                                                 bool AddCurrentAddress)
  : ARMConstantPoolValue((Type*)C->getType(), ID, Kind, PCAdj, Modifier,
                         AddCurrentAddress),
    CVal(C) {}

ARMConstantPoolConstant *
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID) {
  return new ARMConstantPoolConstant(C, ID, ARMCP::CPValue, 0,
                                     ARMCP::no_modifier, false);
}

ARMConstantPoolConstant *
ARMConstantPoolConstant::Create(const GlobalValue *GV,
                                ARMCP::ARMCPModifier Modifier) {
  return new ARMConstantPoolConstant((Type*)Type::getInt32Ty(GV->getContext()),
                                     GV, 0, ARMCP::CPValue, 0,
                                     Modifier, false);
}

ARMConstantPoolConstant *
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID,
                                ARMCP::ARMCPKind Kind, unsigned char PCAdj) {
  return new ARMConstantPoolConstant(C, ID, Kind, PCAdj,
                                     ARMCP::no_modifier, false);
}

ARMConstantPoolConstant *
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID,
                                ARMCP::ARMCPKind Kind, unsigned char PCAdj,
                                ARMCP::ARMCPModifier Modifier,
                                bool AddCurrentAddress) {
  return new ARMConstantPoolConstant(C, ID, Kind, PCAdj, Modifier,
                                     AddCurrentAddress);
}

const GlobalValue *ARMConstantPoolConstant::getGV() const {
  return dyn_cast_or_null<GlobalValue>(CVal);
}

const BlockAddress *ARMConstantPoolConstant::getBlockAddress() const {
  return dyn_cast_or_null<BlockAddress>(CVal);
}

int ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
                                                       unsigned Alignment) {
  unsigned AlignMask = Alignment - 1;
  const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants();
  for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
    if (Constants[i].isMachineConstantPoolEntry() &&
        (Constants[i].getAlignment() & AlignMask) == 0) {
      ARMConstantPoolValue *CPV =
        (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
      ARMConstantPoolConstant *APC = dyn_cast<ARMConstantPoolConstant>(CPV);
      if (!APC) continue;
      if (APC->CVal == CVal && equals(APC))
        return i;
    }
  }

  return -1;
}

bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) {
  const ARMConstantPoolConstant *ACPC = dyn_cast<ARMConstantPoolConstant>(ACPV);
  return ACPC && ACPC->CVal == CVal && ARMConstantPoolValue::hasSameValue(ACPV);
}

void ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
  ID.AddPointer(CVal);
  ARMConstantPoolValue::addSelectionDAGCSEId(ID);
}

void ARMConstantPoolConstant::print(raw_ostream &O) const {
  O << CVal->getName();
  ARMConstantPoolValue::print(O);
}

//===----------------------------------------------------------------------===//
// ARMConstantPoolSymbol
//===----------------------------------------------------------------------===//

ARMConstantPoolSymbol::ARMConstantPoolSymbol(LLVMContext &C, const char *s,
                                             unsigned id,
                                             unsigned char PCAdj,
                                             ARMCP::ARMCPModifier Modifier,
                                             bool AddCurrentAddress)
  : ARMConstantPoolValue(C, id, ARMCP::CPExtSymbol, PCAdj, Modifier,
                         AddCurrentAddress),
    S(strdup(s)) {}

ARMConstantPoolSymbol::~ARMConstantPoolSymbol() {
  free((void*)S);
}

ARMConstantPoolSymbol *
ARMConstantPoolSymbol::Create(LLVMContext &C, const char *s,
                              unsigned ID, unsigned char PCAdj) {
  return new ARMConstantPoolSymbol(C, s, ID, PCAdj, ARMCP::no_modifier, false);
}

static bool CPV_streq(const char *S1, const char *S2) {
  if (S1 == S2)
    return true;
  if (S1 && S2 && strcmp(S1, S2) == 0)
    return true;
  return false;
}

int ARMConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP,
                                                     unsigned Alignment) {
  unsigned AlignMask = Alignment - 1;
  const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants();
  for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
    if (Constants[i].isMachineConstantPoolEntry() &&
        (Constants[i].getAlignment() & AlignMask) == 0) {
      ARMConstantPoolValue *CPV =
        (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
      ARMConstantPoolSymbol *APS = dyn_cast<ARMConstantPoolSymbol>(CPV);
      if (!APS) continue;

      if (CPV_streq(APS->S, S) && equals(APS))
        return i;
    }
  }

  return -1;
}

bool ARMConstantPoolSymbol::hasSameValue(ARMConstantPoolValue *ACPV) {
  const ARMConstantPoolSymbol *ACPS = dyn_cast<ARMConstantPoolSymbol>(ACPV);
  return ACPS && CPV_streq(ACPS->S, S) &&
    ARMConstantPoolValue::hasSameValue(ACPV);
}

void ARMConstantPoolSymbol::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
  ID.AddPointer(S);
  ARMConstantPoolValue::addSelectionDAGCSEId(ID);
}

void ARMConstantPoolSymbol::print(raw_ostream &O) const {
  O << S;
  ARMConstantPoolValue::print(O);
}

//===----------------------------------------------------------------------===//
// ARMConstantPoolMBB
//===----------------------------------------------------------------------===//

ARMConstantPoolMBB::ARMConstantPoolMBB(LLVMContext &C,
                                       const MachineBasicBlock *mbb,
                                       unsigned id, unsigned char PCAdj,
                                       ARMCP::ARMCPModifier Modifier,
                                       bool AddCurrentAddress)
  : ARMConstantPoolValue(C, id, ARMCP::CPMachineBasicBlock, PCAdj,
                         Modifier, AddCurrentAddress),
    MBB(mbb) {}

ARMConstantPoolMBB *ARMConstantPoolMBB::Create(LLVMContext &C,
                                               const MachineBasicBlock *mbb,
                                               unsigned ID,
                                               unsigned char PCAdj) {
  return new ARMConstantPoolMBB(C, mbb, ID, PCAdj, ARMCP::no_modifier, false);
}

int ARMConstantPoolMBB::getExistingMachineCPValue(MachineConstantPool *CP,
                                                  unsigned Alignment) {
  unsigned AlignMask = Alignment - 1;
  const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants();
  for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
    if (Constants[i].isMachineConstantPoolEntry() &&
        (Constants[i].getAlignment() & AlignMask) == 0) {
      ARMConstantPoolValue *CPV =
        (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
      ARMConstantPoolMBB *APMBB = dyn_cast<ARMConstantPoolMBB>(CPV);
      if (!APMBB) continue;

      if (APMBB->MBB == MBB && equals(APMBB))
        return i;
    }
  }

  return -1;
}

bool ARMConstantPoolMBB::hasSameValue(ARMConstantPoolValue *ACPV) {
  const ARMConstantPoolMBB *ACPMBB = dyn_cast<ARMConstantPoolMBB>(ACPV);
  return ACPMBB && ACPMBB->MBB == MBB &&
    ARMConstantPoolValue::hasSameValue(ACPV);
}

void ARMConstantPoolMBB::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
  ID.AddPointer(MBB);
  ARMConstantPoolValue::addSelectionDAGCSEId(ID);
}

void ARMConstantPoolMBB::print(raw_ostream &O) const {
  ARMConstantPoolValue::print(O);
}
<commit_msg>ARMConstantPoolMBB::print should print BB number.<commit_after>//===- ARMConstantPoolValue.cpp - ARM constantpool value --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ARM specific constantpool value class.
//
//===----------------------------------------------------------------------===//

#include "ARMConstantPoolValue.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Constant.h"
#include "llvm/Constants.h"
#include "llvm/GlobalValue.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
using namespace llvm;

//===----------------------------------------------------------------------===//
// ARMConstantPoolValue
//===----------------------------------------------------------------------===//

ARMConstantPoolValue::ARMConstantPoolValue(Type *Ty, unsigned id,
                                           ARMCP::ARMCPKind kind,
                                           unsigned char PCAdj,
                                           ARMCP::ARMCPModifier modifier,
                                           bool addCurrentAddress)
  : MachineConstantPoolValue(Ty), LabelId(id), Kind(kind),
    PCAdjust(PCAdj), Modifier(modifier),
    AddCurrentAddress(addCurrentAddress) {}

ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C, unsigned id,
                                           ARMCP::ARMCPKind kind,
                                           unsigned char PCAdj,
                                           ARMCP::ARMCPModifier modifier,
                                           bool addCurrentAddress)
  : MachineConstantPoolValue((Type*)Type::getInt32Ty(C)),
    LabelId(id), Kind(kind), PCAdjust(PCAdj), Modifier(modifier),
    AddCurrentAddress(addCurrentAddress) {}

ARMConstantPoolValue::~ARMConstantPoolValue() {}

const char *ARMConstantPoolValue::getModifierText() const {
  switch (Modifier) {
  default: llvm_unreachable("Unknown modifier!");
    // FIXME: Are these case sensitive? It'd be nice to lower-case all the
    // strings if that's legal.
  case ARMCP::no_modifier: return "none";
  case ARMCP::TLSGD:       return "tlsgd";
  case ARMCP::GOT:         return "GOT";
  case ARMCP::GOTOFF:      return "GOTOFF";
  case ARMCP::GOTTPOFF:    return "gottpoff";
  case ARMCP::TPOFF:       return "tpoff";
  }
}

int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
                                                    unsigned Alignment) {
  assert(false && "Shouldn't be calling this directly!");
  return -1;
}

void
ARMConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
  ID.AddInteger(LabelId);
  ID.AddInteger(PCAdjust);
}

bool
ARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) {
  if (ACPV->Kind == Kind &&
      ACPV->PCAdjust == PCAdjust &&
      ACPV->Modifier == Modifier) {
    if (ACPV->LabelId == LabelId)
      return true;
    // Two PC relative constpool entries containing the same GV address or
    // external symbols. FIXME: What about blockaddress?
    if (Kind == ARMCP::CPValue || Kind == ARMCP::CPExtSymbol)
      return true;
  }
  return false;
}

void ARMConstantPoolValue::dump() const {
  errs() << "  " << *this;
}

void ARMConstantPoolValue::print(raw_ostream &O) const {
  if (Modifier) O << "(" << getModifierText() << ")";
  if (PCAdjust != 0) {
    O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust;
    if (AddCurrentAddress) O << "-.";
    O << ")";
  }
}

//===----------------------------------------------------------------------===//
// ARMConstantPoolConstant
//===----------------------------------------------------------------------===//

ARMConstantPoolConstant::ARMConstantPoolConstant(Type *Ty,
                                                 const Constant *C,
                                                 unsigned ID,
                                                 ARMCP::ARMCPKind Kind,
                                                 unsigned char PCAdj,
                                                 ARMCP::ARMCPModifier Modifier,
                                                 bool AddCurrentAddress)
  : ARMConstantPoolValue(Ty, ID, Kind, PCAdj, Modifier, AddCurrentAddress),
    CVal(C) {}

ARMConstantPoolConstant::ARMConstantPoolConstant(const Constant *C,
                                                 unsigned ID,
                                                 ARMCP::ARMCPKind Kind,
                                                 unsigned char PCAdj,
                                                 ARMCP::ARMCPModifier Modifier,
                                                 bool AddCurrentAddress)
  : ARMConstantPoolValue((Type*)C->getType(), ID, Kind, PCAdj, Modifier,
                         AddCurrentAddress),
    CVal(C) {}

ARMConstantPoolConstant *
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID) {
  return new ARMConstantPoolConstant(C, ID, ARMCP::CPValue, 0,
                                     ARMCP::no_modifier, false);
}

ARMConstantPoolConstant *
ARMConstantPoolConstant::Create(const GlobalValue *GV,
                                ARMCP::ARMCPModifier Modifier) {
  return new ARMConstantPoolConstant((Type*)Type::getInt32Ty(GV->getContext()),
                                     GV, 0, ARMCP::CPValue, 0,
                                     Modifier, false);
}

ARMConstantPoolConstant *
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID,
                                ARMCP::ARMCPKind Kind, unsigned char PCAdj) {
  return new ARMConstantPoolConstant(C, ID, Kind, PCAdj,
                                     ARMCP::no_modifier, false);
}

ARMConstantPoolConstant *
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID,
                                ARMCP::ARMCPKind Kind, unsigned char PCAdj,
                                ARMCP::ARMCPModifier Modifier,
                                bool AddCurrentAddress) {
  return new ARMConstantPoolConstant(C, ID, Kind, PCAdj, Modifier,
                                     AddCurrentAddress);
}

const GlobalValue *ARMConstantPoolConstant::getGV() const {
  return dyn_cast_or_null<GlobalValue>(CVal);
}

const BlockAddress *ARMConstantPoolConstant::getBlockAddress() const {
  return dyn_cast_or_null<BlockAddress>(CVal);
}

int ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
                                                       unsigned Alignment) {
  unsigned AlignMask = Alignment - 1;
  const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants();
  for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
    if (Constants[i].isMachineConstantPoolEntry() &&
        (Constants[i].getAlignment() & AlignMask) == 0) {
      ARMConstantPoolValue *CPV =
        (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
      ARMConstantPoolConstant *APC = dyn_cast<ARMConstantPoolConstant>(CPV);
      if (!APC) continue;
      if (APC->CVal == CVal && equals(APC))
        return i;
    }
  }

  return -1;
}

bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) {
  const ARMConstantPoolConstant *ACPC = dyn_cast<ARMConstantPoolConstant>(ACPV);
  return ACPC && ACPC->CVal == CVal && ARMConstantPoolValue::hasSameValue(ACPV);
}

void ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
  ID.AddPointer(CVal);
  ARMConstantPoolValue::addSelectionDAGCSEId(ID);
}

void ARMConstantPoolConstant::print(raw_ostream &O) const {
  O << CVal->getName();
  ARMConstantPoolValue::print(O);
}

//===----------------------------------------------------------------------===//
// ARMConstantPoolSymbol
//===----------------------------------------------------------------------===//

ARMConstantPoolSymbol::ARMConstantPoolSymbol(LLVMContext &C, const char *s,
                                             unsigned id,
                                             unsigned char PCAdj,
                                             ARMCP::ARMCPModifier Modifier,
                                             bool AddCurrentAddress)
  : ARMConstantPoolValue(C, id, ARMCP::CPExtSymbol, PCAdj, Modifier,
                         AddCurrentAddress),
    S(strdup(s)) {}

ARMConstantPoolSymbol::~ARMConstantPoolSymbol() {
  free((void*)S);
}

ARMConstantPoolSymbol *
ARMConstantPoolSymbol::Create(LLVMContext &C, const char *s,
                              unsigned ID, unsigned char PCAdj) {
  return new ARMConstantPoolSymbol(C, s, ID, PCAdj, ARMCP::no_modifier, false);
}

static bool CPV_streq(const char *S1, const char *S2) {
  if (S1 == S2)
    return true;
  if (S1 && S2 && strcmp(S1, S2) == 0)
    return true;
  return false;
}

int ARMConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP,
                                                     unsigned Alignment) {
  unsigned AlignMask = Alignment - 1;
  const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants();
  for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
    if (Constants[i].isMachineConstantPoolEntry() &&
        (Constants[i].getAlignment() & AlignMask) == 0) {
      ARMConstantPoolValue *CPV =
        (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
      ARMConstantPoolSymbol *APS = dyn_cast<ARMConstantPoolSymbol>(CPV);
      if (!APS) continue;

      if (CPV_streq(APS->S, S) && equals(APS))
        return i;
    }
  }

  return -1;
}

bool ARMConstantPoolSymbol::hasSameValue(ARMConstantPoolValue *ACPV) {
  const ARMConstantPoolSymbol *ACPS = dyn_cast<ARMConstantPoolSymbol>(ACPV);
  return ACPS && CPV_streq(ACPS->S, S) &&
    ARMConstantPoolValue::hasSameValue(ACPV);
}

void ARMConstantPoolSymbol::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
  ID.AddPointer(S);
  ARMConstantPoolValue::addSelectionDAGCSEId(ID);
}

void ARMConstantPoolSymbol::print(raw_ostream &O) const {
  O << S;
  ARMConstantPoolValue::print(O);
}

//===----------------------------------------------------------------------===//
// ARMConstantPoolMBB
//===----------------------------------------------------------------------===//

ARMConstantPoolMBB::ARMConstantPoolMBB(LLVMContext &C,
                                       const MachineBasicBlock *mbb,
                                       unsigned id, unsigned char PCAdj,
                                       ARMCP::ARMCPModifier Modifier,
                                       bool AddCurrentAddress)
  : ARMConstantPoolValue(C, id, ARMCP::CPMachineBasicBlock, PCAdj,
                         Modifier, AddCurrentAddress),
    MBB(mbb) {}

ARMConstantPoolMBB *ARMConstantPoolMBB::Create(LLVMContext &C,
                                               const MachineBasicBlock *mbb,
                                               unsigned ID,
                                               unsigned char PCAdj) {
  return new ARMConstantPoolMBB(C, mbb, ID, PCAdj, ARMCP::no_modifier, false);
}

int ARMConstantPoolMBB::getExistingMachineCPValue(MachineConstantPool *CP,
                                                  unsigned Alignment) {
  unsigned AlignMask = Alignment - 1;
  const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants();
  for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
    if (Constants[i].isMachineConstantPoolEntry() &&
        (Constants[i].getAlignment() & AlignMask) == 0) {
      ARMConstantPoolValue *CPV =
        (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
      ARMConstantPoolMBB *APMBB = dyn_cast<ARMConstantPoolMBB>(CPV);
      if (!APMBB) continue;

      if (APMBB->MBB == MBB && equals(APMBB))
        return i;
    }
  }

  return -1;
}

bool ARMConstantPoolMBB::hasSameValue(ARMConstantPoolValue *ACPV) {
  const ARMConstantPoolMBB *ACPMBB = dyn_cast<ARMConstantPoolMBB>(ACPV);
  return ACPMBB && ACPMBB->MBB == MBB &&
    ARMConstantPoolValue::hasSameValue(ACPV);
}

void ARMConstantPoolMBB::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
  ID.AddPointer(MBB);
  ARMConstantPoolValue::addSelectionDAGCSEId(ID);
}

void ARMConstantPoolMBB::print(raw_ostream &O) const {
  O << "BB#" << MBB->getNumber();
  ARMConstantPoolValue::print(O);
}
<|endoftext|>


<commit_before>#include "ofApp.h"

void nebulaEye::setup()
{
  sender.setup(OSC_IP, OSC_PORT);
  video.setup();
  flow.setup();
  bgSub.setup();
  contour.setup();
  zone.setup();

  displayGuiGrp.setName("display");
  displayGuiGrp.add(showGui.set("show this menu",true));
  displayGuiGrp.add(showVideo.set("show video",true));
  displayGuiGrp.add(showBgSub.set("show bgsub",true));
  displayGuiGrp.add(bgSubIntensity.set("bg instensity",127,0,255));
  displayGuiGrp.add(showContour.set("show contour",true));
  displayGuiGrp.add(showFlow.set("show motion flow",true));
  displayGuiGrp.add(showZone.set("show zone",true));
  displayGuiGrp.add(showDebug.set("show flow mask",0,0,4));

  gui.setup("nebula-eye","settings.xml",660,10);
  gui.add(displayGuiGrp);
  gui.add(video.guiGrp);
  gui.add(bgSub.guiGrp);
  gui.add(flow.guiGrp);
  gui.add(contour.guiGrp);
  gui.add(zone.guiGrp);

  recordPanel.setup("record", "recordSetting.xml",10, ofGetHeight()-50);
  recordPanel.add(record.set("recording",false));

  ofAddListener(gui.savePressedE, &bgSub, &nebulaBackground::saveAlgoParam);
  showGui.addListener(&bgSub, &nebulaBackground::showGui);
  showZone.addListener(&zone, &nebula::Zone::attach);
  record.addListener(this, &nebulaEye::csvRecordCb);

  gui.loadFromFile("settings.xml");

  ofSetCircleResolution(100);

  ofSetBackgroundColor(0,0,0,0);
}

void nebulaEye::update()
{
  video.update();
  if(video.isFrameNew()){
    img = video.getPixels();
    bgSub.update(img);
    flow.update(img);
    contour.update(bgSub.m_fgmask);

    // create zone mask
    // TODO redraw only on zone change
    zoneMask.resize(3);

    ofVec2f scaledCenter = zone.center.get();

    scaledCenter.x = float(scaledCenter.x) * float(flow.m_flow.cols)/ofGetWidth();
    scaledCenter.y = float(scaledCenter.y) * float(flow.m_flow.rows)/ofGetHeight();
    cv::Point center = ofxCv::toCv(scaledCenter);
    for ( int i = 0; i < zoneMask.size() ; i++ ){
      // clear everything
      zoneMask[i] = cv::Mat::zeros(flow.m_flow.rows, flow.m_flow.cols , CV_8UC1);
      // first draw a white filled circle
      int rad = zone.radius.get()[i] * zoneMask[i].cols / ofGetWidth();
      cv::circle(zoneMask[i], center, rad, cv::Scalar(255,255,255),-1);
    }

    int rad = zone.radius.get()[0] * zoneMask[0].cols / ofGetWidth();
    // then add a black one into the white to mask the other zone(s)
    cv::circle(zoneMask[1], center, rad, cv::Scalar(0),-1);
    rad = zone.radius.get()[1] * zoneMask[0].cols / ofGetWidth();
    cv::circle(zoneMask[2], center, rad, 0,-1);

    // for the last zone, get a white image and draw a black circle
    zoneMask.push_back( cv::Mat::ones(flow.m_flow.rows, flow.m_flow.cols , CV_8UC1)*255 );
    rad = zone.radius.get()[2] * zoneMask[2].cols / ofGetWidth();
    cv::circle(zoneMask[zoneMask.size()-1], center, rad, 0, -1);

    sendOSC();
    recordCSVData();
  }
}

void nebulaEye::draw()
{
  int w(ofGetWidth()), h(ofGetHeight());
  if ( ( ofGetHeight() > 0 && img.getHeight() > 0 ) ) {
    if ( ofGetWidth()/ofGetHeight() > img.getWidth()/img.getHeight()){
      h = ofGetHeight();
      w = h * img.getWidth()/img.getHeight();
    } else if (img.getWidth()>0){
      w = ofGetWidth();
      h = w * img.getHeight()/img.getWidth();
    }
  }

  // ofLogVerbose("ofApp") << "drawing resolution  : " << w << " x " << h;
  ofSetColor(255,255,255);
  if(showVideo)
    video.draw(0,0,w,h);
  if(showBgSub){
    ofSetColor(255,255,255,bgSubIntensity);
    bgSub.draw(0,0,w,h);
  }

  if(showFlow){
    ofSetColor(0,255,0,255);
    flow.draw(0,0,w, h);
  }

  if(showContour){
    ofSetColor(255,255,255);
    contour.draw(0,0,w,h);
  }

  if(showZone){
    ofSetColor(255,0,0,64);
    zone.draw();
  }

  if (showDebug){
    ofSetColor(255);
    int i = showDebug.get()-1;
    ofRectangle rect = ofRectangle(zoneMask[i].cols/2,zoneMask[i].rows/2, zoneMask[i].cols, zoneMask[i].rows);
    ofxCv::drawMat(zoneMask[i],rect.x, rect.y);
    cv::Mat m_flow;
    double zoneFlow = flow.getFlowInMask(zoneMask[i], &m_flow);
    ofVec2f offset(rect.x,rect.y);
    ofVec2f scale(rect.width/m_flow.cols, rect.height/m_flow.rows);
    int stepSize = 4;
    ofPopStyle();
    ofSetColor(0,255,0);
    for(int y = 0; y < m_flow.rows; y += stepSize) {
      for(int x = 0; x < m_flow.cols; x += stepSize) {
        ofVec2f cur = ofVec2f(x, y) * scale + offset;
        const cv::Vec2f& vec = m_flow.at<cv::Vec2f>(y, x);
        ofDrawLine(cur, ofVec2f(x + vec[0], y + vec[1]) * scale + offset);
      }
    }
    ofPushStyle();
    stringstream ss;
    ss << "zone flow : " << zoneFlow;
    ofDrawBitmapString(ss.str(), ofPoint(rect.x+10,rect.y-10));
  }

  if (showGui){
    gui.draw();
  }

  recordPanel.draw();
}

void nebulaEye::exit()
{
}

void nebulaEye::mouseMoved(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mouseDragged(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mousePressed(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mouseReleased(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mouseScrolled(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mouseEntered(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mouseExited(ofMouseEventArgs& mouse)
{
}

void nebulaEye::keyPressed(int key){
  switch (key){
    case 27:
      ofExit();
      break;
    case 'h':
      showGui = !showGui;
      break;
    case 's':
      gui.saveToFile("settings.xml");
      bgSub.saveAlgoParam();
      break;
    default:
      break;
  }
}

void nebulaEye::sendOSC(){
  ofxOscBundle bundle;
  //vector<ofPoint> centroids = contour.getCentroids();
  for (int i = 0; i < contour.finder.size(); i++ ){
    ofxOscMessage m;
    m.setAddress("/b");
    m.addInt32Arg(contour.finder.getLabel(i));
    ofVec2f centroid = ofxCv::toOf(contour.finder.getCentroid(i));
    centroid -= zone.center;
    ofVec2f centroidPol = nebula::Utils::carToPol(centroid);
    centroidPol.y -= zone.angleOrigin;
    centroidPol.y = ofWrapDegrees(centroidPol.y);
    m.addFloatArg(centroidPol.x);
    m.addFloatArg(centroidPol.y);
    m.addFloatArg(contour.finder.getContourArea(i));
    m.addInt32Arg(zone.inside(ofxCv::toOf(contour.finder.getCentroid(i))));
    bundle.addMessage(m);
  }

  ofxOscMessage m;
  m.setAddress("/f");
  flowZone.clear();
  for ( int i = 0; i < zoneMask.size() ; i++ ){
      double f = flow.getFlowInMask(zoneMask[i], NULL);
      flowZone.push_back(f);
      m.addFloatArg(f);
  }
  bundle.addMessage(m);
  sender.sendBundle(bundle);
}

void nebulaEye::csvRecordCb(bool & flag){
  if ( flag ){
    csvRecorder.clear();
    stringstream ss;
    ss << ofGetYear();
    ss << setfill('0') << setw(2) << ofGetMonth();
    ss << setfill('0') << setw(2) << ofGetDay() << "-";
    ss << setfill('0') << setw(2) << ofGetHours();
    ss << setfill('0') << setw(2) << ofGetMinutes();
    ss << setfill('0') << setw(2) << ofGetSeconds() << ".csv";
    ofLog() << "try to create file : " << ss.str();
    csvRecorder.filePath = ofToDataPath(ss.str());
    ofLog() << "record CSV to : " << csvRecorder.filePath;

    int idx(0);
    csvRecorder.setString(0,idx++,"date");
    csvRecorder.setString(0,idx++,"time");
    csvRecorder.setString(0,idx++,"blob x");
    csvRecorder.setString(0,idx++,"blob y");
    csvRecorder.setString(0,idx++,"flow zone 0");
    csvRecorder.setString(0,idx++,"flow zone 1");
    csvRecorder.setString(0,idx++,"flow zone 2");
    csvRecorder.setString(0,idx++,"flow zone 3");

  } else {
    csvRecorder.saveFile();
    // Save the recorded values in the csvRecorder ofxCsv object
    // csvRecorder.saveFile( ofToDataPath( csvFileName ));
    ofLog() << "Saved " << csvRecorder.numRows << " rows to " << csvRecorder.filePath;
  }
}

void nebulaEye::recordCSVData(){

  if (!record) return;

  int row = csvRecorder.numRows;
  int idx = 0;
  csvRecorder.setString(row, 0, getDate());
  csvRecorder.setString(row, 1, getHour());

  int area(0), biggest(-1);
  for (int i = 0; i < contour.finder.size(); i++ ){
    if ( contour.finder.getContourArea(i) > area ){
        biggest = i;
    }
  }

  if ( biggest != -1 ){
    ofVec2f centroid = ofxCv::toOf(contour.finder.getCentroid(biggest));
    centroid -= zone.center;
    ofVec2f centroidPol = nebula::Utils::carToPol(centroid);
    centroidPol.y -= zone.angleOrigin;
    centroidPol.y = ofWrapDegrees(centroidPol.y);

    csvRecorder.setFloat(row,2,centroidPol.x);
    csvRecorder.setFloat(row,3,centroidPol.y);

  } else {
    csvRecorder.setString(row,2,"NA");
    csvRecorder.setString(row,3,"NA");
  }

  csvRecorder.setFloat(row,4,flowZone[0]);
  csvRecorder.setFloat(row,5,flowZone[1]);
  csvRecorder.setFloat(row,6,flowZone[2]);
  csvRecorder.setFloat(row,7,flowZone[3]);

}

string nebulaEye::getDate(){
  stringstream ss;
  ss << setfill('0') << setw(2) << ofGetYear() << "/" << ofGetMonth() << "/" << ofGetDay();
  return ss.str();
}

string nebulaEye::getHour(){
  stringstream ss;
  ss << setfill('0') << setw(2) << ofGetHours() << ":" << ofGetMinutes() << ":" << ofGetSeconds();
  return ss.str();
}
<commit_msg>add millis to recorded time<commit_after>#include "ofApp.h"

void nebulaEye::setup()
{
  sender.setup(OSC_IP, OSC_PORT);
  video.setup();
  flow.setup();
  bgSub.setup();
  contour.setup();
  zone.setup();

  displayGuiGrp.setName("display");
  displayGuiGrp.add(showGui.set("show this menu",true));
  displayGuiGrp.add(showVideo.set("show video",true));
  displayGuiGrp.add(showBgSub.set("show bgsub",true));
  displayGuiGrp.add(bgSubIntensity.set("bg instensity",127,0,255));
  displayGuiGrp.add(showContour.set("show contour",true));
  displayGuiGrp.add(showFlow.set("show motion flow",true));
  displayGuiGrp.add(showZone.set("show zone",true));
  displayGuiGrp.add(showDebug.set("show flow mask",0,0,4));

  gui.setup("nebula-eye","settings.xml",660,10);
  gui.add(displayGuiGrp);
  gui.add(video.guiGrp);
  gui.add(bgSub.guiGrp);
  gui.add(flow.guiGrp);
  gui.add(contour.guiGrp);
  gui.add(zone.guiGrp);

  recordPanel.setup("record", "recordSetting.xml",10, ofGetHeight()-50);
  recordPanel.add(record.set("recording",false));

  ofAddListener(gui.savePressedE, &bgSub, &nebulaBackground::saveAlgoParam);
  showGui.addListener(&bgSub, &nebulaBackground::showGui);
  showZone.addListener(&zone, &nebula::Zone::attach);
  record.addListener(this, &nebulaEye::csvRecordCb);

  gui.loadFromFile("settings.xml");

  ofSetCircleResolution(100);

  ofSetBackgroundColor(0,0,0,0);
}

void nebulaEye::update()
{
  video.update();
  if(video.isFrameNew()){
    img = video.getPixels();
    bgSub.update(img);
    flow.update(img);
    contour.update(bgSub.m_fgmask);

    // create zone mask
    // TODO redraw only on zone change
    zoneMask.resize(3);

    ofVec2f scaledCenter = zone.center.get();

    scaledCenter.x = float(scaledCenter.x) * float(flow.m_flow.cols)/ofGetWidth();
    scaledCenter.y = float(scaledCenter.y) * float(flow.m_flow.rows)/ofGetHeight();
    cv::Point center = ofxCv::toCv(scaledCenter);
    for ( int i = 0; i < zoneMask.size() ; i++ ){
      // clear everything
      zoneMask[i] = cv::Mat::zeros(flow.m_flow.rows, flow.m_flow.cols , CV_8UC1);
      // first draw a white filled circle
      int rad = zone.radius.get()[i] * zoneMask[i].cols / ofGetWidth();
      cv::circle(zoneMask[i], center, rad, cv::Scalar(255,255,255),-1);
    }

    int rad = zone.radius.get()[0] * zoneMask[0].cols / ofGetWidth();
    // then add a black one into the white to mask the other zone(s)
    cv::circle(zoneMask[1], center, rad, cv::Scalar(0),-1);
    rad = zone.radius.get()[1] * zoneMask[0].cols / ofGetWidth();
    cv::circle(zoneMask[2], center, rad, 0,-1);

    // for the last zone, get a white image and draw a black circle
    zoneMask.push_back( cv::Mat::ones(flow.m_flow.rows, flow.m_flow.cols , CV_8UC1)*255 );
    rad = zone.radius.get()[2] * zoneMask[2].cols / ofGetWidth();
    cv::circle(zoneMask[zoneMask.size()-1], center, rad, 0, -1);

    sendOSC();
    recordCSVData();
  }
}

void nebulaEye::draw()
{
  int w(ofGetWidth()), h(ofGetHeight());
  if ( ( ofGetHeight() > 0 && img.getHeight() > 0 ) ) {
    if ( ofGetWidth()/ofGetHeight() > img.getWidth()/img.getHeight()){
      h = ofGetHeight();
      w = h * img.getWidth()/img.getHeight();
    } else if (img.getWidth()>0){
      w = ofGetWidth();
      h = w * img.getHeight()/img.getWidth();
    }
  }

  // ofLogVerbose("ofApp") << "drawing resolution  : " << w << " x " << h;
  ofSetColor(255,255,255);
  if(showVideo)
    video.draw(0,0,w,h);
  if(showBgSub){
    ofSetColor(255,255,255,bgSubIntensity);
    bgSub.draw(0,0,w,h);
  }

  if(showFlow){
    ofSetColor(0,255,0,255);
    flow.draw(0,0,w, h);
  }

  if(showContour){
    ofSetColor(255,255,255);
    contour.draw(0,0,w,h);
  }

  if(showZone){
    ofSetColor(255,0,0,64);
    zone.draw();
  }

  if (showDebug){
    ofSetColor(255);
    int i = showDebug.get()-1;
    ofRectangle rect = ofRectangle(zoneMask[i].cols/2,zoneMask[i].rows/2, zoneMask[i].cols, zoneMask[i].rows);
    ofxCv::drawMat(zoneMask[i],rect.x, rect.y);
    cv::Mat m_flow;
    double zoneFlow = flow.getFlowInMask(zoneMask[i], &m_flow);
    ofVec2f offset(rect.x,rect.y);
    ofVec2f scale(rect.width/m_flow.cols, rect.height/m_flow.rows);
    int stepSize = 4;
    ofPopStyle();
    ofSetColor(0,255,0);
    for(int y = 0; y < m_flow.rows; y += stepSize) {
      for(int x = 0; x < m_flow.cols; x += stepSize) {
        ofVec2f cur = ofVec2f(x, y) * scale + offset;
        const cv::Vec2f& vec = m_flow.at<cv::Vec2f>(y, x);
        ofDrawLine(cur, ofVec2f(x + vec[0], y + vec[1]) * scale + offset);
      }
    }
    ofPushStyle();
    stringstream ss;
    ss << "zone flow : " << zoneFlow;
    ofDrawBitmapString(ss.str(), ofPoint(rect.x+10,rect.y-10));
  }

  if (showGui){
    gui.draw();
  }

  recordPanel.draw();
}

void nebulaEye::exit()
{
}

void nebulaEye::mouseMoved(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mouseDragged(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mousePressed(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mouseReleased(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mouseScrolled(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mouseEntered(ofMouseEventArgs& mouse)
{
}

void nebulaEye::mouseExited(ofMouseEventArgs& mouse)
{
}

void nebulaEye::keyPressed(int key){
  switch (key){
    case 27:
      ofExit();
      break;
    case 'h':
      showGui = !showGui;
      break;
    case 's':
      gui.saveToFile("settings.xml");
      bgSub.saveAlgoParam();
      break;
    default:
      break;
  }
}

void nebulaEye::sendOSC(){
  ofxOscBundle bundle;
  //vector<ofPoint> centroids = contour.getCentroids();
  for (int i = 0; i < contour.finder.size(); i++ ){
    ofxOscMessage m;
    m.setAddress("/b");
    m.addInt32Arg(contour.finder.getLabel(i));
    ofVec2f centroid = ofxCv::toOf(contour.finder.getCentroid(i));
    centroid -= zone.center;
    ofVec2f centroidPol = nebula::Utils::carToPol(centroid);
    centroidPol.y -= zone.angleOrigin;
    centroidPol.y = ofWrapDegrees(centroidPol.y);
    m.addFloatArg(centroidPol.x);
    m.addFloatArg(centroidPol.y);
    m.addFloatArg(contour.finder.getContourArea(i));
    m.addInt32Arg(zone.inside(ofxCv::toOf(contour.finder.getCentroid(i))));
    bundle.addMessage(m);
  }

  ofxOscMessage m;
  m.setAddress("/f");
  flowZone.clear();
  for ( int i = 0; i < zoneMask.size() ; i++ ){
      double f = flow.getFlowInMask(zoneMask[i], NULL);
      flowZone.push_back(f);
      m.addFloatArg(f);
  }
  bundle.addMessage(m);
  sender.sendBundle(bundle);
}

void nebulaEye::csvRecordCb(bool & flag){
  if ( flag ){
    csvRecorder.clear();
    ofResetElapsedTimeCounter();

    stringstream ss;
    ss << ofGetYear();
    ss << setfill('0') << setw(2) << ofGetMonth();
    ss << setfill('0') << setw(2) << ofGetDay() << "-";
    ss << setfill('0') << setw(2) << ofGetHours();
    ss << setfill('0') << setw(2) << ofGetMinutes();
    ss << setfill('0') << setw(2) << ofGetSeconds() << ".csv";
    ofLog() << "try to create file : " << ss.str();
    csvRecorder.filePath = ofToDataPath(ss.str());
    ofLog() << "record CSV to : " << csvRecorder.filePath;

    int idx(0);
    csvRecorder.setString(0,idx++,"date");
    csvRecorder.setString(0,idx++,"time");
    csvRecorder.setString(0,idx++,"blob x");
    csvRecorder.setString(0,idx++,"blob y");
    csvRecorder.setString(0,idx++,"flow zone 0");
    csvRecorder.setString(0,idx++,"flow zone 1");
    csvRecorder.setString(0,idx++,"flow zone 2");
    csvRecorder.setString(0,idx++,"flow zone 3");

  } else {
    csvRecorder.saveFile();
    // Save the recorded values in the csvRecorder ofxCsv object
    // csvRecorder.saveFile( ofToDataPath( csvFileName ));
    ofLog() << "Saved " << csvRecorder.numRows << " rows to " << csvRecorder.filePath;
  }
}

void nebulaEye::recordCSVData(){

  if (!record) return;

  int row = csvRecorder.numRows;
  int idx = 0;
  csvRecorder.setString(row, 0, getDate());
  csvRecorder.setString(row, 1, getHour());

  int area(0), biggest(-1);
  for (int i = 0; i < contour.finder.size(); i++ ){
    if ( contour.finder.getContourArea(i) > area ){
        biggest = i;
    }
  }

  if ( biggest != -1 ){
    ofVec2f centroid = ofxCv::toOf(contour.finder.getCentroid(biggest));
    centroid -= zone.center;
    ofVec2f centroidPol = nebula::Utils::carToPol(centroid);
    centroidPol.y -= zone.angleOrigin;
    centroidPol.y = ofWrapDegrees(centroidPol.y);

    csvRecorder.setFloat(row,2,centroidPol.x);
    csvRecorder.setFloat(row,3,centroidPol.y);

  } else {
    csvRecorder.setString(row,2,"NA");
    csvRecorder.setString(row,3,"NA");
  }

  csvRecorder.setFloat(row,4,flowZone[0]);
  csvRecorder.setFloat(row,5,flowZone[1]);
  csvRecorder.setFloat(row,6,flowZone[2]);
  csvRecorder.setFloat(row,7,flowZone[3]);

}

string nebulaEye::getDate(){
  stringstream ss;
  ss << setfill('0') << setw(2) << ofGetYear() << "/" << ofGetMonth() << "/" << ofGetDay();
  return ss.str();
}

string nebulaEye::getHour(){
  stringstream ss;
  ss << setfill('0') << setw(2) << ofGetHours() << ":" << ofGetMinutes() << ":" << ofGetSeconds() << "." << setw(3) << int(fmod(float(ofGetElapsedTimeMillis()),1000.));
  return ss.str();
}
<|endoftext|>


<commit_before>//===-- NVPTXTargetMachine.cpp - Define TargetMachine for NVPTX -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Top-level implementation for the NVPTX target.
//
//===----------------------------------------------------------------------===//

#include "NVPTXTargetMachine.h"
#include "MCTargetDesc/NVPTXMCAsmInfo.h"
#include "NVPTX.h"
#include "NVPTXAllocaHoisting.h"
#include "NVPTXLowerAggrCopies.h"
#include "NVPTXTargetObjectFile.h"
#include "NVPTXTargetTransformInfo.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Transforms/Scalar.h"

using namespace llvm;

namespace llvm {
void initializeNVVMReflectPass(PassRegistry&);
void initializeGenericToNVVMPass(PassRegistry&);
void initializeNVPTXAllocaHoistingPass(PassRegistry &);
void initializeNVPTXAssignValidGlobalNamesPass(PassRegistry&);
void initializeNVPTXFavorNonGenericAddrSpacesPass(PassRegistry &);
void initializeNVPTXLowerStructArgsPass(PassRegistry &);
}

extern "C" void LLVMInitializeNVPTXTarget() {
  // Register the target.
  RegisterTargetMachine<NVPTXTargetMachine32> X(TheNVPTXTarget32);
  RegisterTargetMachine<NVPTXTargetMachine64> Y(TheNVPTXTarget64);

  // FIXME: This pass is really intended to be invoked during IR optimization,
  // but it's very NVPTX-specific.
  initializeNVVMReflectPass(*PassRegistry::getPassRegistry());
  initializeGenericToNVVMPass(*PassRegistry::getPassRegistry());
  initializeNVPTXAllocaHoistingPass(*PassRegistry::getPassRegistry());
  initializeNVPTXAssignValidGlobalNamesPass(*PassRegistry::getPassRegistry());
  initializeNVPTXFavorNonGenericAddrSpacesPass(
    *PassRegistry::getPassRegistry());
  initializeNVPTXLowerStructArgsPass(*PassRegistry::getPassRegistry());
}

static std::string computeDataLayout(bool is64Bit) {
  std::string Ret = "e";

  if (!is64Bit)
    Ret += "-p:32:32";

  Ret += "-i64:64-v16:16-v32:32-n16:32:64";

  return Ret;
}

NVPTXTargetMachine::NVPTXTargetMachine(const Target &T, StringRef TT,
                                       StringRef CPU, StringRef FS,
                                       const TargetOptions &Options,
                                       Reloc::Model RM, CodeModel::Model CM,
                                       CodeGenOpt::Level OL, bool is64bit)
    : LLVMTargetMachine(T, computeDataLayout(is64bit), TT, CPU, FS, Options, RM,
                        CM, OL),
      is64bit(is64bit), TLOF(make_unique<NVPTXTargetObjectFile>()),
      Subtarget(TT, CPU, FS, *this) {
  if (Triple(TT).getOS() == Triple::NVCL)
    drvInterface = NVPTX::NVCL;
  else
    drvInterface = NVPTX::CUDA;
  initAsmInfo();
}

NVPTXTargetMachine::~NVPTXTargetMachine() {}

void NVPTXTargetMachine32::anchor() {}

NVPTXTargetMachine32::NVPTXTargetMachine32(
    const Target &T, StringRef TT, StringRef CPU, StringRef FS,
    const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
    CodeGenOpt::Level OL)
    : NVPTXTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}

void NVPTXTargetMachine64::anchor() {}

NVPTXTargetMachine64::NVPTXTargetMachine64(
    const Target &T, StringRef TT, StringRef CPU, StringRef FS,
    const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
    CodeGenOpt::Level OL)
    : NVPTXTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}

namespace {
class NVPTXPassConfig : public TargetPassConfig {
public:
  NVPTXPassConfig(NVPTXTargetMachine *TM, PassManagerBase &PM)
      : TargetPassConfig(TM, PM) {}

  NVPTXTargetMachine &getNVPTXTargetMachine() const {
    return getTM<NVPTXTargetMachine>();
  }

  void addIRPasses() override;
  bool addInstSelector() override;
  void addPostRegAlloc() override;
  void addMachineSSAOptimization() override;

  FunctionPass *createTargetRegisterAllocator(bool) override;
  void addFastRegAlloc(FunctionPass *RegAllocPass) override;
  void addOptimizedRegAlloc(FunctionPass *RegAllocPass) override;
};
} // end anonymous namespace

TargetPassConfig *NVPTXTargetMachine::createPassConfig(PassManagerBase &PM) {
  NVPTXPassConfig *PassConfig = new NVPTXPassConfig(this, PM);
  return PassConfig;
}

TargetIRAnalysis NVPTXTargetMachine::getTargetIRAnalysis() {
  return TargetIRAnalysis(
      [this](Function &) { return TargetTransformInfo(NVPTXTTIImpl(this)); });
}

void NVPTXPassConfig::addIRPasses() {
  // The following passes are known to not play well with virtual regs hanging
  // around after register allocation (which in our case, is *all* registers).
  // We explicitly disable them here.  We do, however, need some functionality
  // of the PrologEpilogCodeInserter pass, so we emulate that behavior in the
  // NVPTXPrologEpilog pass (see NVPTXPrologEpilogPass.cpp).
  disablePass(&PrologEpilogCodeInserterID);
  disablePass(&MachineCopyPropagationID);
  disablePass(&BranchFolderPassID);
  disablePass(&TailDuplicateID);

  addPass(createNVPTXImageOptimizerPass());
  TargetPassConfig::addIRPasses();
  addPass(createNVPTXAssignValidGlobalNamesPass());
  addPass(createGenericToNVVMPass());
  addPass(createNVPTXFavorNonGenericAddrSpacesPass());
  addPass(createStraightLineStrengthReducePass());
  addPass(createSeparateConstOffsetFromGEPPass());
  // The SeparateConstOffsetFromGEP pass creates variadic bases that can be used
  // by multiple GEPs. Run GVN or EarlyCSE to really reuse them. GVN generates
  // significantly better code than EarlyCSE for some of our benchmarks.
  if (getOptLevel() == CodeGenOpt::Aggressive)
    addPass(createGVNPass());
  else
    addPass(createEarlyCSEPass());
  // Both FavorNonGenericAddrSpaces and SeparateConstOffsetFromGEP may leave
  // some dead code.  We could remove dead code in an ad-hoc manner, but that
  // requires manual work and might be error-prone.
  //
  // The FavorNonGenericAddrSpaces pass shortcuts unnecessary addrspacecasts,
  // and leave them unused.
  //
  // SeparateConstOffsetFromGEP rebuilds a new index from the old index, and the
  // old index and some of its intermediate results may become unused.
  addPass(createDeadCodeEliminationPass());
}

bool NVPTXPassConfig::addInstSelector() {
  const NVPTXSubtarget &ST =
    getTM<NVPTXTargetMachine>().getSubtarget<NVPTXSubtarget>();

  addPass(createLowerAggrCopies());
  addPass(createAllocaHoisting());
  addPass(createNVPTXISelDag(getNVPTXTargetMachine(), getOptLevel()));

  if (!ST.hasImageHandles())
    addPass(createNVPTXReplaceImageHandlesPass());

  return false;
}

void NVPTXPassConfig::addPostRegAlloc() {
  addPass(createNVPTXPrologEpilogPass(), false);
}

FunctionPass *NVPTXPassConfig::createTargetRegisterAllocator(bool) {
  return nullptr; // No reg alloc
}

void NVPTXPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) {
  assert(!RegAllocPass && "NVPTX uses no regalloc!");
  addPass(&PHIEliminationID);
  addPass(&TwoAddressInstructionPassID);
}

void NVPTXPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
  assert(!RegAllocPass && "NVPTX uses no regalloc!");

  addPass(&ProcessImplicitDefsID);
  addPass(&LiveVariablesID);
  addPass(&MachineLoopInfoID);
  addPass(&PHIEliminationID);

  addPass(&TwoAddressInstructionPassID);
  addPass(&RegisterCoalescerID);

  // PreRA instruction scheduling.
  if (addPass(&MachineSchedulerID))
    printAndVerify("After Machine Scheduling");

  addPass(&StackSlotColoringID);

  // FIXME: Needs physical registers
  //addPass(&PostRAMachineLICMID);

  printAndVerify("After StackSlotColoring");
}

void NVPTXPassConfig::addMachineSSAOptimization() {
  // Pre-ra tail duplication.
  if (addPass(&EarlyTailDuplicateID))
    printAndVerify("After Pre-RegAlloc TailDuplicate");

  // Optimize PHIs before DCE: removing dead PHI cycles may make more
  // instructions dead.
  addPass(&OptimizePHIsID);

  // This pass merges large allocas. StackSlotColoring is a different pass
  // which merges spill slots.
  addPass(&StackColoringID);

  // If the target requests it, assign local variables to stack slots relative
  // to one another and simplify frame index references where possible.
  addPass(&LocalStackSlotAllocationID);

  // With optimization, dead code should already be eliminated. However
  // there is one known exception: lowered code for arguments that are only
  // used by tail calls, where the tail calls reuse the incoming stack
  // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
  addPass(&DeadMachineInstructionElimID);
  printAndVerify("After codegen DCE pass");

  // Allow targets to insert passes that improve instruction level parallelism,
  // like if-conversion. Such passes will typically need dominator trees and
  // loop info, just like LICM and CSE below.
  if (addILPOpts())
    printAndVerify("After ILP optimizations");

  addPass(&MachineLICMID);
  addPass(&MachineCSEID);

  addPass(&MachineSinkingID);
  printAndVerify("After Machine LICM, CSE and Sinking passes");

  addPass(&PeepholeOptimizerID);
  printAndVerify("After codegen peephole optimization pass");
}
<commit_msg>Simplify the query for a subtarget in the NVPTX pass manager.<commit_after>//===-- NVPTXTargetMachine.cpp - Define TargetMachine for NVPTX -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Top-level implementation for the NVPTX target.
//
//===----------------------------------------------------------------------===//

#include "NVPTXTargetMachine.h"
#include "MCTargetDesc/NVPTXMCAsmInfo.h"
#include "NVPTX.h"
#include "NVPTXAllocaHoisting.h"
#include "NVPTXLowerAggrCopies.h"
#include "NVPTXTargetObjectFile.h"
#include "NVPTXTargetTransformInfo.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Transforms/Scalar.h"

using namespace llvm;

namespace llvm {
void initializeNVVMReflectPass(PassRegistry&);
void initializeGenericToNVVMPass(PassRegistry&);
void initializeNVPTXAllocaHoistingPass(PassRegistry &);
void initializeNVPTXAssignValidGlobalNamesPass(PassRegistry&);
void initializeNVPTXFavorNonGenericAddrSpacesPass(PassRegistry &);
void initializeNVPTXLowerStructArgsPass(PassRegistry &);
}

extern "C" void LLVMInitializeNVPTXTarget() {
  // Register the target.
  RegisterTargetMachine<NVPTXTargetMachine32> X(TheNVPTXTarget32);
  RegisterTargetMachine<NVPTXTargetMachine64> Y(TheNVPTXTarget64);

  // FIXME: This pass is really intended to be invoked during IR optimization,
  // but it's very NVPTX-specific.
  initializeNVVMReflectPass(*PassRegistry::getPassRegistry());
  initializeGenericToNVVMPass(*PassRegistry::getPassRegistry());
  initializeNVPTXAllocaHoistingPass(*PassRegistry::getPassRegistry());
  initializeNVPTXAssignValidGlobalNamesPass(*PassRegistry::getPassRegistry());
  initializeNVPTXFavorNonGenericAddrSpacesPass(
    *PassRegistry::getPassRegistry());
  initializeNVPTXLowerStructArgsPass(*PassRegistry::getPassRegistry());
}

static std::string computeDataLayout(bool is64Bit) {
  std::string Ret = "e";

  if (!is64Bit)
    Ret += "-p:32:32";

  Ret += "-i64:64-v16:16-v32:32-n16:32:64";

  return Ret;
}

NVPTXTargetMachine::NVPTXTargetMachine(const Target &T, StringRef TT,
                                       StringRef CPU, StringRef FS,
                                       const TargetOptions &Options,
                                       Reloc::Model RM, CodeModel::Model CM,
                                       CodeGenOpt::Level OL, bool is64bit)
    : LLVMTargetMachine(T, computeDataLayout(is64bit), TT, CPU, FS, Options, RM,
                        CM, OL),
      is64bit(is64bit), TLOF(make_unique<NVPTXTargetObjectFile>()),
      Subtarget(TT, CPU, FS, *this) {
  if (Triple(TT).getOS() == Triple::NVCL)
    drvInterface = NVPTX::NVCL;
  else
    drvInterface = NVPTX::CUDA;
  initAsmInfo();
}

NVPTXTargetMachine::~NVPTXTargetMachine() {}

void NVPTXTargetMachine32::anchor() {}

NVPTXTargetMachine32::NVPTXTargetMachine32(
    const Target &T, StringRef TT, StringRef CPU, StringRef FS,
    const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
    CodeGenOpt::Level OL)
    : NVPTXTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}

void NVPTXTargetMachine64::anchor() {}

NVPTXTargetMachine64::NVPTXTargetMachine64(
    const Target &T, StringRef TT, StringRef CPU, StringRef FS,
    const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
    CodeGenOpt::Level OL)
    : NVPTXTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}

namespace {
class NVPTXPassConfig : public TargetPassConfig {
public:
  NVPTXPassConfig(NVPTXTargetMachine *TM, PassManagerBase &PM)
      : TargetPassConfig(TM, PM) {}

  NVPTXTargetMachine &getNVPTXTargetMachine() const {
    return getTM<NVPTXTargetMachine>();
  }

  void addIRPasses() override;
  bool addInstSelector() override;
  void addPostRegAlloc() override;
  void addMachineSSAOptimization() override;

  FunctionPass *createTargetRegisterAllocator(bool) override;
  void addFastRegAlloc(FunctionPass *RegAllocPass) override;
  void addOptimizedRegAlloc(FunctionPass *RegAllocPass) override;
};
} // end anonymous namespace

TargetPassConfig *NVPTXTargetMachine::createPassConfig(PassManagerBase &PM) {
  NVPTXPassConfig *PassConfig = new NVPTXPassConfig(this, PM);
  return PassConfig;
}

TargetIRAnalysis NVPTXTargetMachine::getTargetIRAnalysis() {
  return TargetIRAnalysis(
      [this](Function &) { return TargetTransformInfo(NVPTXTTIImpl(this)); });
}

void NVPTXPassConfig::addIRPasses() {
  // The following passes are known to not play well with virtual regs hanging
  // around after register allocation (which in our case, is *all* registers).
  // We explicitly disable them here.  We do, however, need some functionality
  // of the PrologEpilogCodeInserter pass, so we emulate that behavior in the
  // NVPTXPrologEpilog pass (see NVPTXPrologEpilogPass.cpp).
  disablePass(&PrologEpilogCodeInserterID);
  disablePass(&MachineCopyPropagationID);
  disablePass(&BranchFolderPassID);
  disablePass(&TailDuplicateID);

  addPass(createNVPTXImageOptimizerPass());
  TargetPassConfig::addIRPasses();
  addPass(createNVPTXAssignValidGlobalNamesPass());
  addPass(createGenericToNVVMPass());
  addPass(createNVPTXFavorNonGenericAddrSpacesPass());
  addPass(createStraightLineStrengthReducePass());
  addPass(createSeparateConstOffsetFromGEPPass());
  // The SeparateConstOffsetFromGEP pass creates variadic bases that can be used
  // by multiple GEPs. Run GVN or EarlyCSE to really reuse them. GVN generates
  // significantly better code than EarlyCSE for some of our benchmarks.
  if (getOptLevel() == CodeGenOpt::Aggressive)
    addPass(createGVNPass());
  else
    addPass(createEarlyCSEPass());
  // Both FavorNonGenericAddrSpaces and SeparateConstOffsetFromGEP may leave
  // some dead code.  We could remove dead code in an ad-hoc manner, but that
  // requires manual work and might be error-prone.
  //
  // The FavorNonGenericAddrSpaces pass shortcuts unnecessary addrspacecasts,
  // and leave them unused.
  //
  // SeparateConstOffsetFromGEP rebuilds a new index from the old index, and the
  // old index and some of its intermediate results may become unused.
  addPass(createDeadCodeEliminationPass());
}

bool NVPTXPassConfig::addInstSelector() {
  const NVPTXSubtarget &ST = *getTM<NVPTXTargetMachine>().getSubtargetImpl();

  addPass(createLowerAggrCopies());
  addPass(createAllocaHoisting());
  addPass(createNVPTXISelDag(getNVPTXTargetMachine(), getOptLevel()));

  if (!ST.hasImageHandles())
    addPass(createNVPTXReplaceImageHandlesPass());

  return false;
}

void NVPTXPassConfig::addPostRegAlloc() {
  addPass(createNVPTXPrologEpilogPass(), false);
}

FunctionPass *NVPTXPassConfig::createTargetRegisterAllocator(bool) {
  return nullptr; // No reg alloc
}

void NVPTXPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) {
  assert(!RegAllocPass && "NVPTX uses no regalloc!");
  addPass(&PHIEliminationID);
  addPass(&TwoAddressInstructionPassID);
}

void NVPTXPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
  assert(!RegAllocPass && "NVPTX uses no regalloc!");

  addPass(&ProcessImplicitDefsID);
  addPass(&LiveVariablesID);
  addPass(&MachineLoopInfoID);
  addPass(&PHIEliminationID);

  addPass(&TwoAddressInstructionPassID);
  addPass(&RegisterCoalescerID);

  // PreRA instruction scheduling.
  if (addPass(&MachineSchedulerID))
    printAndVerify("After Machine Scheduling");

  addPass(&StackSlotColoringID);

  // FIXME: Needs physical registers
  //addPass(&PostRAMachineLICMID);

  printAndVerify("After StackSlotColoring");
}

void NVPTXPassConfig::addMachineSSAOptimization() {
  // Pre-ra tail duplication.
  if (addPass(&EarlyTailDuplicateID))
    printAndVerify("After Pre-RegAlloc TailDuplicate");

  // Optimize PHIs before DCE: removing dead PHI cycles may make more
  // instructions dead.
  addPass(&OptimizePHIsID);

  // This pass merges large allocas. StackSlotColoring is a different pass
  // which merges spill slots.
  addPass(&StackColoringID);

  // If the target requests it, assign local variables to stack slots relative
  // to one another and simplify frame index references where possible.
  addPass(&LocalStackSlotAllocationID);

  // With optimization, dead code should already be eliminated. However
  // there is one known exception: lowered code for arguments that are only
  // used by tail calls, where the tail calls reuse the incoming stack
  // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
  addPass(&DeadMachineInstructionElimID);
  printAndVerify("After codegen DCE pass");

  // Allow targets to insert passes that improve instruction level parallelism,
  // like if-conversion. Such passes will typically need dominator trees and
  // loop info, just like LICM and CSE below.
  if (addILPOpts())
    printAndVerify("After ILP optimizations");

  addPass(&MachineLICMID);
  addPass(&MachineCSEID);

  addPass(&MachineSinkingID);
  printAndVerify("After Machine LICM, CSE and Sinking passes");

  addPass(&PeepholeOptimizerID);
  printAndVerify("After codegen peephole optimization pass");
}
<|endoftext|>