<commit_before>#include "menu/menu.h"
#include "menu/menu_option.h"
#include "util/bitmap.h"
#include "util/funcs.h"
#include "util/keyboard.h"
#include "util/sound.h"
#include "util/token.h"
#include "util/tokenreader.h"
#include "globals.h"
#include "init.h"
#include "music.h"

// Options :O
#include "menu/option_adventure.h"
#include "menu/option_background.h"
#include "menu/option_credits.h"
#include "menu/option_key.h"
#include "menu/option_menu.h"
#include "menu/option_versus.h"

#include <queue>

Bitmap *Menu::work = 0;

static std::queue<std::string> lastPlayed;

static std::queue<MenuOption *> backgrounds;

const int yellow = Bitmap::makeColor( 255, 255, 0 );
const int white = Bitmap::makeColor( 255, 255, 255 );

RectArea::RectArea() : x(0), y(0), width(0), height(0)
{
}

RectArea::RectArea(int x, int y, int w, int h)
{
	this->x  = x;
	this->y  = y;
	this->width  = width;
	this->height  = height;
}

bool RectArea::empty()
{
	return (x==0 && y==0 && width==0 && height==0);
}

Menu::Menu() : music(""), background(0), position(), vFont(0), fontWidth(32), fontHeight(32), _name("")
{
	if(!work)work = new Bitmap(Bitmap::Screen->getWidth(), Bitmap::Screen->getHeight()); //Bitmap::Screen;
}

void Menu::load(Token *token)throw( LoadException )
{
	if ( *token != "menu" )
		throw LoadException("Not a menu");

	while ( token->hasTokens() )
	{
		try
		{
			Token * tok;
			*token >> tok;
			if ( *tok == "name" )
			{
				// Set menu name
				*tok >> _name;
			}
			else if ( *tok == "music" )
			{
				// Set music and push onto the stack
				*tok >> music;

				lastPlayed.push(music);
			}
			else if ( *tok == "background" )
			{
				// Create new background and push onto the stack
				background = new OptionBg(tok);

				backgrounds.push(background);
			}
			else if ( *tok == "position" )
			{
				// This handles the placement of the menu list
				*tok >> position.x >> position.y >> position.width >> position.height;
			}
			else if ( *tok == "font" )
			{
				std::string temp;
				*tok >> temp >> fontWidth >> fontHeight;
				vFont = new FreeTypeFont(temp);
				vFont->setSize(fontWidth,fontHeight);
			}
			else if ( *tok == "menu" )
			{
				// Create a sub menu
				OptionMenu *temp = new OptionMenu(tok);
				menuOptions.push_back(temp);
			}
			else if ( *tok == "key" )
			{
				// Reconfigure a given key
				OptionKey *temp = new OptionKey(tok);
				menuOptions.push_back(temp);
			}
			else if ( *tok == "adventure" )
			{
				// Adventure mode
				OptionAdventure *temp = new OptionAdventure(tok);
				menuOptions.push_back(temp);
			}
			else if ( *tok == "versus" )
			{
				// Versus mode
				OptionVersus *temp = new OptionVersus(tok);
				menuOptions.push_back(temp);
			}
			else if ( *tok == "credits" )
			{
				// Credits mode
				OptionCredits *temp = new OptionCredits(tok);
				menuOptions.push_back(temp);
			}
			else if ( *tok == "back" || *tok == "quit" )
			{
				// Create a menu option ie options, controller config, adventure, versus, credits, etc

				//menuOptions.push_back();
			}
			else
			{
				cout<<"Unhandled menu attribute: "<<endl;
				tok->print(" ");
			}
		}
		catch ( const TokenException & ex )
		{
			// delete current;
			string m( "Menu parse error: " );
			m += ex.getReason();
			throw LoadException( m );
		}
		catch ( const LoadException & ex )
		{
			// delete current;
			throw ex;
		}
	}

	if(_name.empty())throw LoadException("No name set, the menu should have a name!");
	if(backgrounds.empty())throw LoadException("There should be at least one background in the entire menu!");
	if(position.empty())throw LoadException("The position for the menu list must be set!");

	if(!vFont)
	{
		std::string f = Util::getDataPath() + "/fonts/arial.ttf";
		vFont = new FreeTypeFont(f);
		vFont->setSize(fontWidth,fontHeight);
	}

	// Finally lets assign list order numering
	for(unsigned int i = 0; i < menuOptions.size();++i)
	{
		menuOptions[i]->setID(i);
	}

}

void Menu::load(const std::string &filename)throw( LoadException )
{
	// Must check for initial token, menu
	TokenReader tr( filename );

	// Token * current = tr.readToken();
	Token * token = tr.readToken();
	load(token);
}

void Menu::run() throw(ReturnException)
{

	Keyboard key;

	key.setDelay( Keyboard::Key_UP, 300 );
	key.setDelay( Keyboard::Key_DOWN, 300 );
	key.setDelay( Keyboard::Key_ENTER, 300 );
	key.setDelay( Keyboard::Key_LEFT, 50 );
	key.setDelay( Keyboard::Key_RIGHT, 50 );

	Bitmap screen_buffer( 320, 240 );
	bool done = false;
	bool endGame = false;

	if(menuOptions.empty())throw ReturnException();
	selectedOption = menuOptions.begin();
	menuOptions.front()->setState(MenuOption::Selected);

	while( !endGame )
	{
		Global::speed_counter = 0;
		Global::second_counter = 0;
		int game_time = 100;

		if(music != "" && music != lastPlayed.front())
		{
			//Music::pause();
			//Music::fadeIn( 0.3 );
			//Music::loadSong( Util::getDataPath() + music );
			//Music::play();
		}
		while ( ! done && (*selectedOption)->getState() != MenuOption::Run ){

			bool draw = false;
			key.poll();

			if ( Global::speed_counter > 0 )
			{
				draw = true;
				// Keys

				if ( key[ Keyboard::Key_UP ] )
				{
					(*selectedOption)->setState(MenuOption::Deselected);
					if(selectedOption > menuOptions.begin())selectedOption--;
					(*selectedOption)->setState(MenuOption::Selected);
				}

				if ( key[ Keyboard::Key_DOWN ] )
				{
					(*selectedOption)->setState(MenuOption::Deselected);
					if(selectedOption < menuOptions.begin()+menuOptions.size()-1)selectedOption++;
					(*selectedOption)->setState(MenuOption::Selected);
				}

				if( key[ Keyboard::Key_ENTER ] )
				{
					(*selectedOption)->setState(MenuOption::Run);
				}

				// Logic
				if(backgrounds.front())backgrounds.front()->logic();

				std::vector <MenuOption *>::iterator b = menuOptions.begin();
				std::vector <MenuOption *>::iterator e = menuOptions.end();
				for(;b!=e;++b)
				{
					(*b)->logic();
				}

				Global::speed_counter = 0;
			}

			while ( Global::second_counter > 0 )
			{
				game_time--;
				Global::second_counter--;
				if ( game_time < 0 )
					game_time = 0;
			}

			if ( draw )
			{
				// Draw
				if(backgrounds.front())backgrounds.front()->draw(work);

				std::vector <MenuOption *>::iterator b = menuOptions.begin();
				std::vector <MenuOption *>::iterator e = menuOptions.end();
				for(int i=0;b!=e;++b,++i)
				{
					/* There more than likely won't be any need to draw, but hey maybe sometime in the future
					   the need might arise */
					(*b)->draw(work);

					// These menus are temporary, they will need to be changed
					const unsigned int color = ((*b)->getState() == MenuOption::Selected) ? yellow : white;
					vFont->printf( position.x, int(position.y + i * fontHeight *1.2), color, *work, (*b)->getText(), 0 );
				}

				// Finally render to screen
				work->BlitToScreen();
			}

			while ( Global::speed_counter < 1 )
			{
				Util::rest( 1 );
				key.poll();
			}

			endGame = done |= key[ Keyboard::Key_ESC ];
		}

		// do we got an option to run, lets do it
		if((*selectedOption)->getState() == MenuOption::Run)
		{
			(*selectedOption)->run(endGame);
			// Reset it's state
			(*selectedOption)->setState(MenuOption::Selected);
		}
		if(endGame)
		{
			//  pop out any backgrounds pushed onto the stack reseting it to the old one if applicable
			if(backgrounds.size() >= 2)
			{
				delete backgrounds.front();
				backgrounds.pop();
				background = backgrounds.front();
			}
			if(lastPlayed.back() == music)
			{
				lastPlayed.pop();
				//Music::pause();
				//Music::fadeIn( 0.3 );
				//Music::loadSong( Util::getDataPath() + lastPlayed.front() );
				//Music::play();

			}
		}
	}
}

const std::string &Menu::getName()
{
	return _name;
}

void Menu::setBitmap(Bitmap *bmp)
{
	work = bmp;
}

Menu::~Menu()
{
	// cleanup
	std::vector <MenuOption *>::iterator b = menuOptions.begin();
	std::vector <MenuOption *>::iterator e = menuOptions.end();
	for(;b!=e;++b)
	{
		if((*b))delete (*b);
	}

	while(!backgrounds.empty())
	{
		delete backgrounds.front();
		backgrounds.pop();
	}
	//if(background)delete background;
	if(vFont)delete vFont;
}

<commit_msg>Menu works teh coolness<commit_after>#include "menu/menu.h"
#include "menu/menu_option.h"
#include "util/bitmap.h"
#include "util/funcs.h"
#include "util/keyboard.h"
#include "util/sound.h"
#include "util/token.h"
#include "util/tokenreader.h"
#include "globals.h"
#include "init.h"
#include "music.h"

// Options :O
#include "menu/option_adventure.h"
#include "menu/option_background.h"
#include "menu/option_credits.h"
#include "menu/option_key.h"
#include "menu/option_menu.h"
#include "menu/option_versus.h"

#include <queue>

Bitmap *Menu::work = 0;

static std::queue<std::string> lastPlayed;

static std::queue<MenuOption *> backgrounds;

const int yellow = Bitmap::makeColor( 255, 255, 0 );
const int white = Bitmap::makeColor( 255, 255, 255 );

RectArea::RectArea() : x(0), y(0), width(0), height(0)
{
}

RectArea::RectArea(int x, int y, int w, int h)
{
	this->x  = x;
	this->y  = y;
	this->width  = width;
	this->height  = height;
}

bool RectArea::empty()
{
	return (x==0 && y==0 && width==0 && height==0);
}

Menu::Menu() : music(""), background(0), position(), vFont(0), fontWidth(32), fontHeight(32), _name("")
{
	if(!work)work = new Bitmap(Bitmap::Screen->getWidth(), Bitmap::Screen->getHeight()); //Bitmap::Screen;
}

void Menu::load(Token *token)throw( LoadException )
{
	if ( *token != "menu" )
		throw LoadException("Not a menu");

	while ( token->hasTokens() )
	{
		try
		{
			Token * tok;
			*token >> tok;
			if ( *tok == "name" )
			{
				// Set menu name
				*tok >> _name;
			}
			else if ( *tok == "music" )
			{
				// Set music and push onto the stack
				*tok >> music;

				lastPlayed.push(music);
			}
			else if ( *tok == "background" )
			{
				// Create new background and push onto the stack
				background = new OptionBg(tok);

				backgrounds.push(background);
			}
			else if ( *tok == "position" )
			{
				// This handles the placement of the menu list
				*tok >> position.x >> position.y >> position.width >> position.height;
			}
			else if ( *tok == "font" )
			{
				std::string temp;
				*tok >> temp >> fontWidth >> fontHeight;
				vFont = new FreeTypeFont(temp);
				vFont->setSize(fontWidth,fontHeight);
			}
			else if ( *tok == "menu" )
			{
				// Create a sub menu
				OptionMenu *temp = new OptionMenu(tok);
				menuOptions.push_back(temp);
			}
			else if ( *tok == "key" )
			{
				// Reconfigure a given key
				OptionKey *temp = new OptionKey(tok);
				menuOptions.push_back(temp);
			}
			else if ( *tok == "adventure" )
			{
				// Adventure mode
				OptionAdventure *temp = new OptionAdventure(tok);
				menuOptions.push_back(temp);
			}
			else if ( *tok == "versus" )
			{
				// Versus mode
				OptionVersus *temp = new OptionVersus(tok);
				menuOptions.push_back(temp);
			}
			else if ( *tok == "credits" )
			{
				// Credits mode
				OptionCredits *temp = new OptionCredits(tok);
				menuOptions.push_back(temp);
			}
			else if ( *tok == "back" || *tok == "quit" )
			{
				// Create a menu option ie options, controller config, adventure, versus, credits, etc

				//menuOptions.push_back();
			}
			else
			{
				cout<<"Unhandled menu attribute: "<<endl;
				tok->print(" ");
			}
		}
		catch ( const TokenException & ex )
		{
			// delete current;
			string m( "Menu parse error: " );
			m += ex.getReason();
			throw LoadException( m );
		}
		catch ( const LoadException & ex )
		{
			// delete current;
			throw ex;
		}
	}

	if(_name.empty())throw LoadException("No name set, the menu should have a name!");
	if(backgrounds.empty())throw LoadException("There should be at least one background in the entire menu!");
	if(position.empty())throw LoadException("The position for the menu list must be set!");

	if(!vFont)
	{
		std::string f = Util::getDataPath() + "/fonts/arial.ttf";
		vFont = new FreeTypeFont(f);
		vFont->setSize(fontWidth,fontHeight);
	}

	// Finally lets assign list order numering
	for(unsigned int i = 0; i < menuOptions.size();++i)
	{
		menuOptions[i]->setID(i);
	}

}

void Menu::load(const std::string &filename)throw( LoadException )
{
	// Must check for initial token, menu
	TokenReader tr( filename );

	// Token * current = tr.readToken();
	Token * token = tr.readToken();
	load(token);
}

void Menu::run() throw(ReturnException)
{

	Keyboard key;

	key.setDelay( Keyboard::Key_UP, 300 );
	key.setDelay( Keyboard::Key_DOWN, 300 );
	key.setDelay( Keyboard::Key_ENTER, 300 );
	key.setDelay( Keyboard::Key_LEFT, 50 );
	key.setDelay( Keyboard::Key_RIGHT, 50 );

	Bitmap screen_buffer( 320, 240 );
	bool done = false;
	bool endGame = false;

	if(menuOptions.empty())throw ReturnException();
	selectedOption = menuOptions.begin();
	menuOptions.front()->setState(MenuOption::Selected);

	while( !endGame )
	{
		Global::speed_counter = 0;
		Global::second_counter = 0;
		int game_time = 100;

		if(music != "" && music != lastPlayed.front())
		{
			//Music::pause();
			//Music::fadeIn( 0.3 );
			//Music::loadSong( Util::getDataPath() + music );
			//Music::play();
		}
		while ( ! done && (*selectedOption)->getState() != MenuOption::Run ){

			bool draw = false;
			key.poll();

			if ( Global::speed_counter > 0 )
			{
				draw = true;
				// Keys

				if ( key[ Keyboard::Key_UP ] )
				{
					(*selectedOption)->setState(MenuOption::Deselected);
					if(selectedOption > menuOptions.begin())selectedOption--;
					(*selectedOption)->setState(MenuOption::Selected);
				}

				if ( key[ Keyboard::Key_DOWN ] )
				{
					(*selectedOption)->setState(MenuOption::Deselected);
					if(selectedOption < menuOptions.begin()+menuOptions.size()-1)selectedOption++;
					(*selectedOption)->setState(MenuOption::Selected);
				}

				if( key[ Keyboard::Key_ENTER ] )
				{
					(*selectedOption)->setState(MenuOption::Run);
				}

				// Logic
				if(backgrounds.front())backgrounds.front()->logic();

				std::vector <MenuOption *>::iterator b = menuOptions.begin();
				std::vector <MenuOption *>::iterator e = menuOptions.end();
				for(;b!=e;++b)
				{
					(*b)->logic();
				}

				Global::speed_counter = 0;
			}

			while ( Global::second_counter > 0 )
			{
				game_time--;
				Global::second_counter--;
				if ( game_time < 0 )
					game_time = 0;
			}

			if ( draw )
			{
				// Draw
				if(backgrounds.front())backgrounds.front()->draw(work);

				std::vector <MenuOption *>::iterator b = menuOptions.begin();
				std::vector <MenuOption *>::iterator e = menuOptions.end();
				for(int i=0;b!=e;++b,++i)
				{
					/* There more than likely won't be any need to draw, but hey maybe sometime in the future
					   the need might arise */
					(*b)->draw(work);

					// These menus are temporary, they will need to be changed
					const unsigned int color = ((*b)->getState() == MenuOption::Selected) ? yellow : white;
					vFont->printf( position.x, int(position.y + i * fontHeight *1.2), color, *work, (*b)->getText(), 0 );
				}

				// Finally render to screen
				work->BlitToScreen();
			}

			while ( Global::speed_counter < 1 )
			{
				Util::rest( 1 );
				key.poll();
			}

			endGame = done |= key[ Keyboard::Key_ESC ];
		}

		// Stupid keyboard
		key.wait();
		// do we got an option to run, lets do it
		if((*selectedOption)->getState() == MenuOption::Run)
		{
			(*selectedOption)->run(endGame);
			// Reset it's state
			(*selectedOption)->setState(MenuOption::Selected);
		}
		if(endGame)
		{
			//  pop out any backgrounds pushed onto the stack reseting it to the old one if applicable
			if(backgrounds.size() >= 2)
			{
				delete backgrounds.front();
				backgrounds.pop();
				background = backgrounds.front();
			}
			if(lastPlayed.back() == music)
			{
				lastPlayed.pop();
				//Music::pause();
				//Music::fadeIn( 0.3 );
				//Music::loadSong( Util::getDataPath() + lastPlayed.front() );
				//Music::play();

			}
		}
	}
}

const std::string &Menu::getName()
{
	return _name;
}

void Menu::setBitmap(Bitmap *bmp)
{
	work = bmp;
}

Menu::~Menu()
{
	// cleanup
	std::vector <MenuOption *>::iterator b = menuOptions.begin();
	std::vector <MenuOption *>::iterator e = menuOptions.end();
	for(;b!=e;++b)
	{
		if((*b))delete (*b);
	}

	while(!backgrounds.empty())
	{
		delete backgrounds.front();
		backgrounds.pop();
	}
	//if(background)delete background;
	if(vFont)delete vFont;
}

<|endoftext|>


<commit_before>// Copyright 2019 The Souper Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "souper/Infer/Interpreter.h"

namespace souper {
  EvalValue evaluateAddNSW(llvm::APInt a, llvm::APInt b) {
    bool Ov;
    auto Res = a.sadd_ov(b, Ov);
    if (Ov)
      return EvalValue::poison();
    else
      return Res;
  }

  EvalValue evaluateAddNUW(llvm::APInt a, llvm::APInt b) {
    bool Ov;
    auto Res = a.uadd_ov(b, Ov);
    if (Ov)
      return EvalValue::poison();
    else
      return Res;
  }

  EvalValue evaluateAddNW(llvm::APInt a, llvm::APInt b) {
    bool Ov1, Ov2;
    auto Res1 = a.sadd_ov(b, Ov1);
    auto Res2 = a.uadd_ov(b, Ov2);
    if (Ov1 || Ov2)
      return EvalValue::poison();
    else
      return Res1;
  }

  EvalValue evaluateSubNSW(llvm::APInt a, llvm::APInt b) {
    bool Ov;
    auto Res = a.ssub_ov(b, Ov);
    if (Ov)
      return EvalValue::poison();
    else
      return Res;
  }

  EvalValue evaluateSubNUW(llvm::APInt a, llvm::APInt b) {
    bool Ov;
    auto Res = a.usub_ov(b, Ov);
    if (Ov)
      return EvalValue::poison();
    else
      return Res;
  }

  EvalValue evaluateSubNW(llvm::APInt a, llvm::APInt b) {
    bool Ov1, Ov2;
    auto Res1 = a.ssub_ov(b, Ov1);
    auto Res2 = a.usub_ov(b, Ov2);
    if (Ov1 || Ov2)
      return EvalValue::poison();
    else
      return Res1;
  }

  EvalValue evaluateUDiv(llvm::APInt a, llvm::APInt b) {
    if (b == 0)
      return EvalValue::ub();
    return {a.udiv(b)};
  }

  EvalValue evaluateURem(llvm::APInt a, llvm::APInt b) {
    if (b == 0)
      return EvalValue::ub();
    return {a.urem(b)};
  }

  EvalValue evaluateShl(llvm::APInt a, llvm::APInt b) {
    if (b.uge(a.getBitWidth()))
      return EvalValue::poison();
    return {a << b};
  }

  EvalValue evaluateLShr(llvm::APInt a, llvm::APInt b) {
    if (b.uge(a.getBitWidth()))
      return EvalValue::poison();
    return {a.lshr(b)};
  }

  EvalValue evaluateAShr(llvm::APInt a, llvm::APInt b) {
    if (b.uge(a.getBitWidth()))
      return EvalValue::poison();
    return {a.ashr(b)};
  }

#define ARG0 Args[0].getValue()
#define ARG1 Args[1].getValue()
#define ARG2 Args[2].getValue()

  EvalValue ConcreteInterpreter::evaluateSingleInst(Inst *Inst, std::vector<EvalValue> &Args) {
    // UB propagates unconditionally
    for (auto &A : Args)
      if (A.K == EvalValue::ValueKind::UB)
        return EvalValue::ub();

    // phi and select only take poison from their chosen input
    if (Inst->K != Inst::Select) {
      for (auto &A : Args)
        if (A.K == EvalValue::ValueKind::Poison)
          return EvalValue::poison();
    }

    for (auto &A : Args)
      if (A.K == EvalValue::ValueKind::Undef)
        llvm::report_fatal_error("undef not supported by interpreter");

    switch (Inst->K) {
    case Inst::Const:
      return {Inst->Val};

    case Inst::UntypedConst:
      return {Inst->Val};

    case Inst::Var:
      llvm::report_fatal_error("Interpreter can't find an input value, exiting");

    case Inst::Phi:
      // FIXME should return all values not just one of them
      // At this moment, the only situation where evaluateInst is called on an
      // Instcontaining Phi is for the purpose of partial evaluation during
      // abstract interpretation. In this case, it is okay to return one of the
      // operands. If we ever want to deterministically interpret an LHS
      // containing a phi, this needs to start returning a list, or there needs
      // to be enough information in BlockPCs to interpret ARG0
      return Args[0];

    case Inst::Add:
      return {ARG0 + ARG1};

    case Inst::AddNSW:
      return evaluateAddNSW(ARG0, ARG1);

    case Inst::AddNUW:
      return evaluateAddNUW(ARG0, ARG1);

    case Inst::AddNW:
      return evaluateAddNW(ARG0, ARG1);

    case Inst::Sub:
      return {ARG0 - ARG1};

    case Inst::SubNSW:
      return evaluateSubNSW(ARG0, ARG1);

    case Inst::SubNUW:
      return evaluateSubNUW(ARG0, ARG1);

    case Inst::SubNW:
      return evaluateSubNW(ARG0, ARG1);

    case Inst::Mul:
      return {ARG0 * ARG1};

    case Inst::MulNSW:{
      bool Ov;
      auto Res = ARG0.smul_ov(ARG1, Ov);
      if (Ov)
        return EvalValue::poison();
      else
        return Res;
    }

    case Inst::MulNUW:{
      bool Ov;
      auto Res = ARG0.umul_ov(ARG1, Ov);
      if (Ov)
        return EvalValue::poison();
      else
        return Res;
    }

    case Inst::MulNW:{
      bool Ov1, Ov2;
      auto Res1 = ARG0.smul_ov(ARG1, Ov1);
      auto Res2 = ARG0.umul_ov(ARG1, Ov2);
      if (Ov1 || Ov2)
        return EvalValue::poison();
      else
        return Res1;
    }

    case Inst::UDivExact:
      if (ARG1 == 0)
        return EvalValue::ub();
      if ((ARG0.udiv(ARG1) * ARG1) != ARG0)
        return EvalValue::poison();
      return {ARG0.udiv(ARG1)};

    case Inst::UDiv:
      return evaluateUDiv(ARG0, ARG1);

    case Inst::SDivExact:
      if (ARG1 == 0 ||
          (ARG0.isMinSignedValue() && ARG1.isAllOnesValue()))
        return EvalValue::ub();
      if ((ARG0.sdiv(ARG1) * ARG1) != ARG0)
        return EvalValue::poison();
      return {ARG0.sdiv(ARG1)};

    case Inst::SDiv:
      if (ARG1 == 0 ||
          (ARG0.isMinSignedValue() && ARG1 == -1))
        return EvalValue::ub();
      return {ARG0.sdiv(ARG1)};

    case Inst::URem:
      return evaluateURem(ARG0, ARG1);

    case Inst::SRem:
      if (ARG1 == 0 ||
          (ARG0.isMinSignedValue() && ARG1.isAllOnesValue()))
        return EvalValue::ub();
      return {ARG0.srem(ARG1)};

    case Inst::And:
      return {ARG0 & ARG1};

    case Inst::Or:
      return {ARG0 | ARG1};

    case Inst::Xor:
      return {ARG0 ^ ARG1};

    case Inst::Shl:
      return evaluateShl(ARG0, ARG1);

    case Inst::ShlNSW:{
      bool Ov;
      auto Res = ARG0.sshl_ov(ARG1, Ov);
      if (Ov)
        return EvalValue::poison();
      return Res;
    }

    case Inst::ShlNUW:{
      bool Ov;
      auto Res = ARG0.ushl_ov(ARG1, Ov);
      if (Ov)
        return EvalValue::poison();
      return Res;
    }

    case Inst::ShlNW:{
      bool Ov1, Ov2;
      auto Res1 = ARG0.ushl_ov(ARG1, Ov1);
      auto Res2 = ARG0.sshl_ov(ARG1, Ov2);
      if (Ov1 || Ov2)
        return EvalValue::poison();
      return Res1;
    }

    case Inst::LShr:
      return evaluateLShr(ARG0, ARG1);

    case Inst::LShrExact:{
      if (ARG1.uge(ARG0.getBitWidth()))
        return EvalValue::poison();
      auto Res = ARG0.lshr(ARG1);
      if (ARG0 != Res.shl(ARG1))
        return EvalValue::poison();
      return Res;
    }

    case Inst::AShr:
      return evaluateAShr(ARG0, ARG1);

    case Inst::AShrExact:{
      if (ARG1.uge(ARG0.getBitWidth()))
        return EvalValue::poison();
      auto Res = ARG0.ashr(ARG1);
      if (ARG0 != Res.shl(ARG1))
        return EvalValue::poison();
      return Res;
    }

    case Inst::Select:
      if (!Args[0].hasValue())
        return Args[0];
      return ARG0.getBoolValue() ? Args[1] : Args[2];

    case Inst::ZExt:
      return {ARG0.zext(Inst->Width)};

    case Inst::SExt:
      return {ARG0.sext(Inst->Width)};

    case Inst::Trunc:
      return {ARG0.trunc(Inst->Width)};

    case Inst::Eq:
      return {{1, ARG0 == ARG1}};

    case Inst::Ne:
      return {{1, ARG0 != ARG1}};

    case Inst::Ult:
      return {{1, ARG0.ult(ARG1)}};

    case Inst::Slt:
      return {{1, ARG0.slt(ARG1)}};

    case Inst::Ule:
      return {{1, ARG0.ule(ARG1)}};

    case Inst::Sle:
      return {{1, ARG0.sle(ARG1)}};

    case Inst::CtPop:
      return {llvm::APInt(Inst->Width, ARG0.countPopulation())};

    case Inst::Ctlz:
      return {llvm::APInt(Inst->Width,
                          ARG0.countLeadingZeros())};

    case Inst::Cttz:
      return {llvm::APInt(Inst->Width,
                          ARG0.countTrailingZeros())};

    case Inst::BSwap:
      return {ARG0.byteSwap()};

    case Inst::BitReverse:
      return {ARG0.reverseBits()};

    case Inst::FShl:{
      unsigned W = ARG0.getBitWidth();
      auto Input = (ARG0.zext(2 * W).shl(W)) | ARG1.zext(2 * W);
      auto Output = Input.shl(ARG2.urem(W));
      return {Output.extractBits(W, W)};
    }

    case Inst::FShr:{
      unsigned W = ARG0.getBitWidth();
      auto Input = (ARG0.zext(2 * W).shl(W)) | ARG1.zext(2 * W);
      auto Output = Input.lshr(ARG2.urem(W));
      return {Output.extractBits(W, 0)};
    }

    // TODO implement these
    case Inst::ExtractValue:
    case Inst::SAddWithOverflow:
    case Inst::SAddO:
    case Inst::UAddWithOverflow:
    case Inst::UAddO:
    case Inst::SSubWithOverflow:
    case Inst::SSubO:
    case Inst::USubWithOverflow:
    case Inst::USubO:
    case Inst::SMulWithOverflow:
    case Inst::SMulO:
    case Inst::UMulWithOverflow:
    case Inst::UMulO:
      return {EvalValue()};

    default:
      llvm::report_fatal_error("unimplemented instruction kind " +
                               std::string(Inst::getKindName(Inst->K)) +
                               " in interpreter");
    }
  }

#undef ARG0
#undef ARG1
#undef ARG2

  EvalValue ConcreteInterpreter::evaluateInst(Inst *Root) {
    if (Cache.find(Root) != Cache.end())
      return Cache[Root];

    // TODO SmallVector
    std::vector<EvalValue> EvaluatedArgs;
    for (auto &&I : Root->Ops)
      EvaluatedArgs.push_back(evaluateInst(I));
    auto Result = evaluateSingleInst(Root, EvaluatedArgs);
    if (CacheWritable)
      Cache[Root] = Result;
    return Result;
  }
}
<commit_msg>Teach concrete interpreter about saturating add/sub<commit_after>// Copyright 2019 The Souper Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "souper/Infer/Interpreter.h"

namespace souper {
  EvalValue evaluateAddNSW(llvm::APInt a, llvm::APInt b) {
    bool Ov;
    auto Res = a.sadd_ov(b, Ov);
    if (Ov)
      return EvalValue::poison();
    else
      return Res;
  }

  EvalValue evaluateAddNUW(llvm::APInt a, llvm::APInt b) {
    bool Ov;
    auto Res = a.uadd_ov(b, Ov);
    if (Ov)
      return EvalValue::poison();
    else
      return Res;
  }

  EvalValue evaluateAddNW(llvm::APInt a, llvm::APInt b) {
    bool Ov1, Ov2;
    auto Res1 = a.sadd_ov(b, Ov1);
    auto Res2 = a.uadd_ov(b, Ov2);
    if (Ov1 || Ov2)
      return EvalValue::poison();
    else
      return Res1;
  }

  EvalValue evaluateSubNSW(llvm::APInt a, llvm::APInt b) {
    bool Ov;
    auto Res = a.ssub_ov(b, Ov);
    if (Ov)
      return EvalValue::poison();
    else
      return Res;
  }

  EvalValue evaluateSubNUW(llvm::APInt a, llvm::APInt b) {
    bool Ov;
    auto Res = a.usub_ov(b, Ov);
    if (Ov)
      return EvalValue::poison();
    else
      return Res;
  }

  EvalValue evaluateSubNW(llvm::APInt a, llvm::APInt b) {
    bool Ov1, Ov2;
    auto Res1 = a.ssub_ov(b, Ov1);
    auto Res2 = a.usub_ov(b, Ov2);
    if (Ov1 || Ov2)
      return EvalValue::poison();
    else
      return Res1;
  }

  EvalValue evaluateUDiv(llvm::APInt a, llvm::APInt b) {
    if (b == 0)
      return EvalValue::ub();
    return {a.udiv(b)};
  }

  EvalValue evaluateURem(llvm::APInt a, llvm::APInt b) {
    if (b == 0)
      return EvalValue::ub();
    return {a.urem(b)};
  }

  EvalValue evaluateShl(llvm::APInt a, llvm::APInt b) {
    if (b.uge(a.getBitWidth()))
      return EvalValue::poison();
    return {a << b};
  }

  EvalValue evaluateLShr(llvm::APInt a, llvm::APInt b) {
    if (b.uge(a.getBitWidth()))
      return EvalValue::poison();
    return {a.lshr(b)};
  }

  EvalValue evaluateAShr(llvm::APInt a, llvm::APInt b) {
    if (b.uge(a.getBitWidth()))
      return EvalValue::poison();
    return {a.ashr(b)};
  }

#define ARG0 Args[0].getValue()
#define ARG1 Args[1].getValue()
#define ARG2 Args[2].getValue()

  EvalValue ConcreteInterpreter::evaluateSingleInst(Inst *Inst, std::vector<EvalValue> &Args) {
    // UB propagates unconditionally
    for (auto &A : Args)
      if (A.K == EvalValue::ValueKind::UB)
        return EvalValue::ub();

    // phi and select only take poison from their chosen input
    if (Inst->K != Inst::Select) {
      for (auto &A : Args)
        if (A.K == EvalValue::ValueKind::Poison)
          return EvalValue::poison();
    }

    for (auto &A : Args)
      if (A.K == EvalValue::ValueKind::Undef)
        llvm::report_fatal_error("undef not supported by interpreter");

    switch (Inst->K) {
    case Inst::Const:
      return {Inst->Val};

    case Inst::UntypedConst:
      return {Inst->Val};

    case Inst::Var:
      llvm::report_fatal_error("Interpreter can't find an input value, exiting");

    case Inst::Phi:
      // FIXME should return all values not just one of them
      // At this moment, the only situation where evaluateInst is called on an
      // Instcontaining Phi is for the purpose of partial evaluation during
      // abstract interpretation. In this case, it is okay to return one of the
      // operands. If we ever want to deterministically interpret an LHS
      // containing a phi, this needs to start returning a list, or there needs
      // to be enough information in BlockPCs to interpret ARG0
      return Args[0];

    case Inst::Add:
      return {ARG0 + ARG1};

    case Inst::AddNSW:
      return evaluateAddNSW(ARG0, ARG1);

    case Inst::AddNUW:
      return evaluateAddNUW(ARG0, ARG1);

    case Inst::AddNW:
      return evaluateAddNW(ARG0, ARG1);

    case Inst::Sub:
      return {ARG0 - ARG1};

    case Inst::SubNSW:
      return evaluateSubNSW(ARG0, ARG1);

    case Inst::SubNUW:
      return evaluateSubNUW(ARG0, ARG1);

    case Inst::SubNW:
      return evaluateSubNW(ARG0, ARG1);

    case Inst::Mul:
      return {ARG0 * ARG1};

    case Inst::MulNSW:{
      bool Ov;
      auto Res = ARG0.smul_ov(ARG1, Ov);
      if (Ov)
        return EvalValue::poison();
      else
        return Res;
    }

    case Inst::MulNUW:{
      bool Ov;
      auto Res = ARG0.umul_ov(ARG1, Ov);
      if (Ov)
        return EvalValue::poison();
      else
        return Res;
    }

    case Inst::MulNW:{
      bool Ov1, Ov2;
      auto Res1 = ARG0.smul_ov(ARG1, Ov1);
      auto Res2 = ARG0.umul_ov(ARG1, Ov2);
      if (Ov1 || Ov2)
        return EvalValue::poison();
      else
        return Res1;
    }

    case Inst::UDivExact:
      if (ARG1 == 0)
        return EvalValue::ub();
      if ((ARG0.udiv(ARG1) * ARG1) != ARG0)
        return EvalValue::poison();
      return {ARG0.udiv(ARG1)};

    case Inst::UDiv:
      return evaluateUDiv(ARG0, ARG1);

    case Inst::SDivExact:
      if (ARG1 == 0 ||
          (ARG0.isMinSignedValue() && ARG1.isAllOnesValue()))
        return EvalValue::ub();
      if ((ARG0.sdiv(ARG1) * ARG1) != ARG0)
        return EvalValue::poison();
      return {ARG0.sdiv(ARG1)};

    case Inst::SDiv:
      if (ARG1 == 0 ||
          (ARG0.isMinSignedValue() && ARG1 == -1))
        return EvalValue::ub();
      return {ARG0.sdiv(ARG1)};

    case Inst::URem:
      return evaluateURem(ARG0, ARG1);

    case Inst::SRem:
      if (ARG1 == 0 ||
          (ARG0.isMinSignedValue() && ARG1.isAllOnesValue()))
        return EvalValue::ub();
      return {ARG0.srem(ARG1)};

    case Inst::And:
      return {ARG0 & ARG1};

    case Inst::Or:
      return {ARG0 | ARG1};

    case Inst::Xor:
      return {ARG0 ^ ARG1};

    case Inst::Shl:
      return evaluateShl(ARG0, ARG1);

    case Inst::ShlNSW:{
      bool Ov;
      auto Res = ARG0.sshl_ov(ARG1, Ov);
      if (Ov)
        return EvalValue::poison();
      return Res;
    }

    case Inst::ShlNUW:{
      bool Ov;
      auto Res = ARG0.ushl_ov(ARG1, Ov);
      if (Ov)
        return EvalValue::poison();
      return Res;
    }

    case Inst::ShlNW:{
      bool Ov1, Ov2;
      auto Res1 = ARG0.ushl_ov(ARG1, Ov1);
      auto Res2 = ARG0.sshl_ov(ARG1, Ov2);
      if (Ov1 || Ov2)
        return EvalValue::poison();
      return Res1;
    }

    case Inst::LShr:
      return evaluateLShr(ARG0, ARG1);

    case Inst::LShrExact:{
      if (ARG1.uge(ARG0.getBitWidth()))
        return EvalValue::poison();
      auto Res = ARG0.lshr(ARG1);
      if (ARG0 != Res.shl(ARG1))
        return EvalValue::poison();
      return Res;
    }

    case Inst::AShr:
      return evaluateAShr(ARG0, ARG1);

    case Inst::AShrExact:{
      if (ARG1.uge(ARG0.getBitWidth()))
        return EvalValue::poison();
      auto Res = ARG0.ashr(ARG1);
      if (ARG0 != Res.shl(ARG1))
        return EvalValue::poison();
      return Res;
    }

    case Inst::Select:
      if (!Args[0].hasValue())
        return Args[0];
      return ARG0.getBoolValue() ? Args[1] : Args[2];

    case Inst::ZExt:
      return {ARG0.zext(Inst->Width)};

    case Inst::SExt:
      return {ARG0.sext(Inst->Width)};

    case Inst::Trunc:
      return {ARG0.trunc(Inst->Width)};

    case Inst::Eq:
      return {{1, ARG0 == ARG1}};

    case Inst::Ne:
      return {{1, ARG0 != ARG1}};

    case Inst::Ult:
      return {{1, ARG0.ult(ARG1)}};

    case Inst::Slt:
      return {{1, ARG0.slt(ARG1)}};

    case Inst::Ule:
      return {{1, ARG0.ule(ARG1)}};

    case Inst::Sle:
      return {{1, ARG0.sle(ARG1)}};

    case Inst::CtPop:
      return {llvm::APInt(Inst->Width, ARG0.countPopulation())};

    case Inst::Ctlz:
      return {llvm::APInt(Inst->Width,
                          ARG0.countLeadingZeros())};

    case Inst::Cttz:
      return {llvm::APInt(Inst->Width,
                          ARG0.countTrailingZeros())};

    case Inst::BSwap:
      return {ARG0.byteSwap()};

    case Inst::BitReverse:
      return {ARG0.reverseBits()};

    case Inst::FShl:{
      unsigned W = ARG0.getBitWidth();
      auto Input = (ARG0.zext(2 * W).shl(W)) | ARG1.zext(2 * W);
      auto Output = Input.shl(ARG2.urem(W));
      return {Output.extractBits(W, W)};
    }

    case Inst::FShr:{
      unsigned W = ARG0.getBitWidth();
      auto Input = (ARG0.zext(2 * W).shl(W)) | ARG1.zext(2 * W);
      auto Output = Input.lshr(ARG2.urem(W));
      return {Output.extractBits(W, 0)};
    }

    case Inst::SAddSat:
      return { ARG0.sadd_sat(ARG1) };

    case Inst::UAddSat:
      return { ARG0.uadd_sat(ARG1) };

    case Inst::SSubSat:
      return { ARG0.ssub_sat(ARG1) };

    case Inst::USubSat:
      return { ARG0.usub_sat(ARG1) };

    // TODO implement these
    case Inst::ExtractValue:
    case Inst::SAddWithOverflow:
    case Inst::SAddO:
    case Inst::UAddWithOverflow:
    case Inst::UAddO:
    case Inst::SSubWithOverflow:
    case Inst::SSubO:
    case Inst::USubWithOverflow:
    case Inst::USubO:
    case Inst::SMulWithOverflow:
    case Inst::SMulO:
    case Inst::UMulWithOverflow:
    case Inst::UMulO:
      return {EvalValue()};

    default:
      llvm::report_fatal_error("unimplemented instruction kind " +
                               std::string(Inst::getKindName(Inst->K)) +
                               " in interpreter");
    }
  }

#undef ARG0
#undef ARG1
#undef ARG2

  EvalValue ConcreteInterpreter::evaluateInst(Inst *Root) {
    if (Cache.find(Root) != Cache.end())
      return Cache[Root];

    // TODO SmallVector
    std::vector<EvalValue> EvaluatedArgs;
    for (auto &&I : Root->Ops)
      EvaluatedArgs.push_back(evaluateInst(I));
    auto Result = evaluateSingleInst(Root, EvaluatedArgs);
    if (CacheWritable)
      Cache[Root] = Result;
    return Result;
  }
}
<|endoftext|>


<commit_before>#include "messenger.h"

<commit_msg>Removing last cpp file in src directory<commit_after><|endoftext|>


<commit_before>#include "LIBSN.H"

#include <stdio.h>
#include <assert.h>

int fileHandle = 0;

int PCinit()
{
	assert(0);
	return 0;
}

int PCopen(char* name, int flags, int perms)
{
	switch (flags)
	{
	case 0:
		fileHandle = (int)fopen(name, "rb");
		break;
	case 1:
		fileHandle = (int)fopen(name, "wb");
		break;
	case 2:
		fileHandle = (int)fopen(name, "rwb");
		break;
	}

	return fileHandle == 0 ? -1 : fileHandle;
}

int PCcreat(char* name, int perms)
{
	assert(0);
	return 0;
}

int PClseek(int fd, int offset, int mode)
{
	return fseek((FILE*)fileHandle, offset, mode);
}

int PCread(int fd, char* buff, int len)
{
	return fread(buff, len, 1, (FILE*)fileHandle);
}

int PCwrite(int fd, char* buff, int len)
{
	return fwrite(buff, len, 1, (FILE*)fileHandle);
}

int PCclose(int fd)
{
	assert(0);
	return 0;
}
<commit_msg>Emulate PCclose<commit_after>#include "LIBSN.H"

#include <stdio.h>
#include <assert.h>

int fileHandle = 0;

int PCinit()
{
	assert(0);
	return 0;
}

int PCopen(char* name, int flags, int perms)
{
	switch (flags)
	{
	case 0:
		fileHandle = (int)fopen(name, "rb");
		break;
	case 1:
		fileHandle = (int)fopen(name, "wb");
		break;
	case 2:
		fileHandle = (int)fopen(name, "rwb");
		break;
	}

	return fileHandle == 0 ? -1 : fileHandle;
}

int PCcreat(char* name, int perms)
{
	assert(0);
	return 0;
}

int PClseek(int fd, int offset, int mode)
{
	return fseek((FILE*)fileHandle, offset, mode);
}

int PCread(int fd, char* buff, int len)
{
	return fread(buff, len, 1, (FILE*)fileHandle);
}

int PCwrite(int fd, char* buff, int len)
{
	return fwrite(buff, len, 1, (FILE*)fileHandle);
}

int PCclose(int fd)
{
	return fclose((FILE*)fd);
}
<|endoftext|>


<commit_before>//  Natron
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
*Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
*contact: immarespond at gmail dot com
*
*/

#include "Image.h"

#include "Engine/Lut.h"

RectI Natron::Bitmap::minimalNonMarkedBbox(const RectI& roi) const
{
    /*if we rendered everything we just append
     a NULL box to indicate we rendered it all.*/
//    if(!memchr(_map.get(),0,_rod.area())){
//        ret.push_back(RectI());
//        return ret;
//    }

    RectI bbox = roi;
    //find bottom
    for (int i = bbox.bottom(); i < bbox.top();++i) {
        char* buf = &_map[(i-_rod.bottom())*_rod.width()];
        if(!memchr(buf, 0, _rod.width())){
            bbox.set_bottom(bbox.bottom()+1);
        } else {
            break;
        }
    }

    //find top (will do zero iteration if the bbox is already empty)
    for (int i = bbox.top()-1; i >= bbox.bottom();--i) {
        char* buf = &_map[(i-_rod.bottom())*_rod.width()];
        if (!memchr(buf, 0, _rod.width())) {
            bbox.set_top(bbox.top()-1);
        } else {
            break;
        }
    }

    // avoid making bbox.width() iterations for nothing
    if (bbox.isNull()) {
        return bbox;
    }

    //find left
    for (int j = bbox.left(); j < bbox.right(); ++j) {
        bool shouldStop = false;
        for (int i = bbox.bottom(); i < bbox.top(); ++i) {
            if (!_map[(i-_rod.bottom())*_rod.width() + (j-_rod.left())]) {
                shouldStop = true;
                break;
            }
        }
        if (!shouldStop) {
            bbox.set_left(bbox.left()+1);
        } else {
            break;
        }
    }

    //find right
    for (int j = bbox.right()-1; j >= bbox.left(); --j) {
        bool shouldStop = false;
        for (int i = bbox.bottom(); i < bbox.top(); ++i) {
            if (!_map[(i-_rod.bottom())*_rod.width() + (j-_rod.left())]) {
                shouldStop = true;
                break;
            }
        }
        if (!shouldStop) {
            bbox.set_right(bbox.right()-1);
        } else {
            break;
        }
    }
    return bbox;
}

std::list<RectI> Natron::Bitmap::minimalNonMarkedRects(const RectI& roi) const
{
    /*for now a simple version that computes the bbox*/
    std::list<RectI> ret;

    RectI bbox = minimalNonMarkedBbox(roi);
//#define NATRON_BITMAP_DISABLE_OPTIMIZATION
#ifndef NATRON_BITMAP_DISABLE_OPTIMIZATION
    if (bbox.isNull()) {
        return ret; // return an empty rectangle list
    }

    // optimization by Fred, Jan 31, 2014
    //
    // Now that we have the smallest enclosing bounding box,
    // let's try to find rectangles for the bottom, the top,
    // the left and the right part.
    // This happens quite often, for example when zooming out
    // (in this case the area to compute is formed of A, B, C and D,
    // and X is already rendered), or when panning (in this case the area
    // is just two rectangles, e.g. A and C, and the rectangles B, D and
    // X are already rendered).
    // The rectangles A, B, C and D from the following drawing are just
    // zeroes, and X contains zeroes and ones.
    //
    // BBBBBBBBBBBBBB
    // BBBBBBBBBBBBBB
    // CXXXXXXXXXXDDD
    // CXXXXXXXXXXDDD
    // CXXXXXXXXXXDDD
    // CXXXXXXXXXXDDD
    // AAAAAAAAAAAAAA

    // First, find if there's an "A" rectangle, and push it to the result
    //find bottom
    RectI bbox_sub = bbox;
    bbox_sub.set_top(bbox.bottom());
    for (int i = bbox.bottom(); i < bbox.top();++i) {
        char* buf = &_map[(i-_rod.bottom())*_rod.width()];
        if (!memchr(buf, 1, _rod.width())) {
            bbox.set_bottom(bbox.bottom()+1);
            bbox_sub.set_top(bbox.bottom());
        } else {
            break;
        }
    }
    if (!bbox_sub.isNull()) { // empty boxes should not be pushed
        ret.push_back(bbox_sub);
    }

    // Now, find the "B" rectangle
    //find top
    bbox_sub = bbox;
    bbox_sub.set_bottom(bbox.top());
    for (int i = bbox.top()-1; i >= bbox.bottom();--i) {
        char* buf = &_map[(i-_rod.bottom())*_rod.width()];
        if (!memchr(buf, 1, _rod.width())) {
            bbox.set_top(bbox.top()-1);
            bbox_sub.set_bottom(bbox.top());
        } else {
            break;
        }
    }
    if (!bbox_sub.isNull()) { // empty boxes should not be pushed
        ret.push_back(bbox_sub);
    }

    //find left
    bbox_sub = bbox;
    bbox_sub.set_right(bbox.left());
    for (int j = bbox.left(); j < bbox.right(); ++j) {
        bool shouldStop = false;
        for (int i = bbox.bottom(); i < bbox.top(); ++i) {
            if (_map[(i-_rod.bottom())*_rod.width()+(j-_rod.left())]) {
                shouldStop = true;
                break;
            }
        }
        if (!shouldStop) {
            bbox.set_left(bbox.left()+1);
            bbox_sub.set_right(bbox.left());
        } else {
            break;
        }
    }
    if (!bbox_sub.isNull()) { // empty boxes should not be pushed
        ret.push_back(bbox_sub);
    }

    //find right
    bbox_sub = bbox;
    bbox_sub.set_left(bbox.right());
    for (int j = bbox.right()-1; j >= bbox.left(); --j) {
        bool shouldStop = false;
        for (int i = bbox.bottom(); i < bbox.top(); ++i) {
            if (_map[(i-_rod.bottom())*_rod.width()+(j-_rod.left())]) {
                shouldStop = true;
                break;
            }
        }
        if (!shouldStop) {
            bbox.set_right(bbox.right()-1);
            bbox_sub.set_left(bbox.right());
        } else {
            break;
        }
    }

    // get the bounding box of what's left (the X rectangle in the drawing above)
    bbox = minimalNonMarkedBbox(bbox);
#endif // NATRON_BITMAP_DISABLE_OPTIMIZATION
    if (!bbox.isNull()) { // empty boxes should not be pushed
        ret.push_back(bbox);
    }
    //qDebug() << "render " << ret.size() << " rectangles";
    return ret;
}

void Natron::Bitmap::markForRendered(const RectI& roi){
    for (int i = roi.bottom(); i < roi.top();++i) {
        char* buf = &_map[(i-_rod.bottom())*_rod.width()];
        memset(buf, 1, roi.width());
    }
}

void Natron::Image::copy(const Natron::Image& other){

    RectI intersection;
    this->_params._rod.intersect(other._params._rod, &intersection);

    if (intersection.isNull()) {
        return;
    }

    const float* src = other.pixelAt(0, 0);
    float* dst = pixelAt(0, 0);
    memcpy(dst, src, intersection.area());
}

namespace Natron{
    void debugImage(Natron::Image* img,const QString& filename){
        const RectI& rod = img->getRoD();
        QImage output(rod.width(),rod.height(),QImage::Format_ARGB32);
        const Natron::Color::Lut* lut = Natron::Color::LutManager::sRGBLut();
        lut->to_byte_packed(output.bits(), img->pixelAt(0, 0), rod, rod, rod,
                            Natron::Color::PACKING_RGBA,Natron::Color::PACKING_BGRA, true,false);
        U64 hashKey = img->getHashKey();
        QString hashKeyStr = QString::number(hashKey);
        QString realFileName = filename.isEmpty() ? QString(hashKeyStr+".png") : filename;
        output.save(realFileName);
    }

}

<commit_msg>more debugging.<commit_after>//  Natron
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
*Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
*contact: immarespond at gmail dot com
*
*/

#include "Image.h"

#include "Engine/Lut.h"

RectI Natron::Bitmap::minimalNonMarkedBbox(const RectI& roi) const
{
    /*if we rendered everything we just append
     a NULL box to indicate we rendered it all.*/
//    if(!memchr(_map.get(),0,_rod.area())){
//        ret.push_back(RectI());
//        return ret;
//    }

    RectI bbox = roi;
    //find bottom
    for (int i = bbox.bottom(); i < bbox.top();++i) {
        char* buf = &_map[(i-_rod.bottom())*_rod.width()];
        if(!memchr(buf, 0, _rod.width())){
            bbox.set_bottom(bbox.bottom()+1);
        } else {
            break;
        }
    }

    //find top (will do zero iteration if the bbox is already empty)
    for (int i = bbox.top()-1; i >= bbox.bottom();--i) {
        char* buf = &_map[(i-_rod.bottom())*_rod.width()];
        if (!memchr(buf, 0, _rod.width())) {
            bbox.set_top(bbox.top()-1);
        } else {
            break;
        }
    }

    // avoid making bbox.width() iterations for nothing
    if (bbox.isNull()) {
        return bbox;
    }

    //find left
    for (int j = bbox.left(); j < bbox.right(); ++j) {
        bool shouldStop = false;
        for (int i = bbox.bottom(); i < bbox.top(); ++i) {
            if (!_map[(i-_rod.bottom())*_rod.width() + (j-_rod.left())]) {
                shouldStop = true;
                break;
            }
        }
        if (!shouldStop) {
            bbox.set_left(bbox.left()+1);
        } else {
            break;
        }
    }

    //find right
    for (int j = bbox.right()-1; j >= bbox.left(); --j) {
        bool shouldStop = false;
        for (int i = bbox.bottom(); i < bbox.top(); ++i) {
            if (!_map[(i-_rod.bottom())*_rod.width() + (j-_rod.left())]) {
                shouldStop = true;
                break;
            }
        }
        if (!shouldStop) {
            bbox.set_right(bbox.right()-1);
        } else {
            break;
        }
    }
    return bbox;
}

std::list<RectI> Natron::Bitmap::minimalNonMarkedRects(const RectI& roi) const
{
    std::list<RectI> ret;

    RectI bboxM = minimalNonMarkedBbox(roi);
//#define NATRON_BITMAP_DISABLE_OPTIMIZATION
#ifdef NATRON_BITMAP_DISABLE_OPTIMIZATION
    if (!bboxM.isNull()) { // empty boxes should not be pushed
        ret.push_back(bbox);
    }
#else
    if (bboxM.isNull()) {
        return ret; // return an empty rectangle list
    }

    // optimization by Fred, Jan 31, 2014
    //
    // Now that we have the smallest enclosing bounding box,
    // let's try to find rectangles for the bottom, the top,
    // the left and the right part.
    // This happens quite often, for example when zooming out
    // (in this case the area to compute is formed of A, B, C and D,
    // and X is already rendered), or when panning (in this case the area
    // is just two rectangles, e.g. A and C, and the rectangles B, D and
    // X are already rendered).
    // The rectangles A, B, C and D from the following drawing are just
    // zeroes, and X contains zeroes and ones.
    //
    // BBBBBBBBBBBBBB
    // BBBBBBBBBBBBBB
    // CXXXXXXXXXXDDD
    // CXXXXXXXXXXDDD
    // CXXXXXXXXXXDDD
    // CXXXXXXXXXXDDD
    // AAAAAAAAAAAAAA

    // First, find if there's an "A" rectangle, and push it to the result
    //find bottom
    RectI bboxX = bboxM;
    RectI bboxA = bboxX;
    bboxA.set_top(bboxX.bottom());
    for (int i = bboxX.bottom(); i < bboxX.top();++i) {
        char* buf = &_map[(i-_rod.bottom())*_rod.width()];
        if (!memchr(buf, 1, _rod.width())) {
            bboxX.set_bottom(bboxX.bottom()+1);
            bboxA.set_top(bboxX.bottom());
        } else {
            break;
        }
    }
    if (!bboxA.isNull()) { // empty boxes should not be pushed
        ret.push_back(bboxA);
    }

    // Now, find the "B" rectangle
    //find top
    RectI bboxB = bboxX;
    bboxB.set_bottom(bboxX.top());
    for (int i = bboxX.top()-1; i >= bboxX.bottom();--i) {
        char* buf = &_map[(i-_rod.bottom())*_rod.width()];
        if (!memchr(buf, 1, _rod.width())) {
            bboxX.set_top(bboxX.top()-1);
            bboxB.set_bottom(bboxX.top());
        } else {
            break;
        }
    }
    if (!bboxB.isNull()) { // empty boxes should not be pushed
        ret.push_back(bboxB);
    }

    //find left
    RectI bboxC = bboxX;
    bboxC.set_right(bboxX.left());
    for (int j = bboxX.left(); j < bboxX.right(); ++j) {
        bool shouldStop = false;
        for (int i = bboxX.bottom(); i < bboxX.top(); ++i) {
            if (_map[(i-_rod.bottom())*_rod.width()+(j-_rod.left())]) {
                shouldStop = true;
                break;
            }
        }
        if (!shouldStop) {
            bboxX.set_left(bboxX.left()+1);
            bboxC.set_right(bboxX.left());
        } else {
            break;
        }
    }
    if (!bboxC.isNull()) { // empty boxes should not be pushed
        ret.push_back(bboxC);
    }

    //find right
    RectI bboxD = bboxX;
    bboxD.set_left(bboxX.right());
    for (int j = bboxX.right()-1; j >= bboxX.left(); --j) {
        bool shouldStop = false;
        for (int i = bboxX.bottom(); i < bboxX.top(); ++i) {
            if (_map[(i-_rod.bottom())*_rod.width()+(j-_rod.left())]) {
                shouldStop = true;
                break;
            }
        }
        if (!shouldStop) {
            bboxX.set_right(bboxX.right()-1);
            bboxD.set_left(bboxX.right());
        } else {
            break;
        }
    }

    assert(bboxA.bottom() == bboxM.bottom());
    assert(bboxA.left() == bboxM.left());
    assert(bboxA.right() == bboxM.right());
    assert(bboxA.top() == bboxX.bottom());

    assert(bboxB.top() == bboxM.top());
    assert(bboxB.left() == bboxM.left());
    assert(bboxB.right() == bboxM.right());
    assert(bboxB.bottom() == bboxX.top());

    assert(bboxC.top() == bboxX.top());
    assert(bboxC.left() == bboxM.left());
    assert(bboxC.right() == bboxX.left());
    assert(bboxC.bottom() == bboxX.bottom());

    assert(bboxD.top() == bboxX.top());
    assert(bboxD.left() == bboxX.right());
    assert(bboxD.right() == bboxM.right());
    assert(bboxD.bottom() == bboxX.bottom());

    // get the bounding box of what's left (the X rectangle in the drawing above)
    bboxX = minimalNonMarkedBbox(bboxX);
    if (!bboxX.isNull()) { // empty boxes should not be pushed
        ret.push_back(bboxX);
    }

#endif // NATRON_BITMAP_DISABLE_OPTIMIZATION
    qDebug() << "render " << ret.size() << " rectangles";
    for (std::list<RectI>::const_iterator it = ret.begin(); it != ret.end(); ++it) {
        qDebug() << "rect: " << it->x1 << ',' << it->x2 << ',' << it->y1 << ',' << it->y2;
    }
    return ret;
}

void Natron::Bitmap::markForRendered(const RectI& roi){
    for (int i = roi.bottom(); i < roi.top();++i) {
        char* buf = &_map[(i-_rod.bottom())*_rod.width()];
        memset(buf, 1, roi.width());
    }
}

void Natron::Image::copy(const Natron::Image& other){

    RectI intersection;
    this->_params._rod.intersect(other._params._rod, &intersection);

    if (intersection.isNull()) {
        return;
    }

    const float* src = other.pixelAt(0, 0);
    float* dst = pixelAt(0, 0);
    memcpy(dst, src, intersection.area());
}

namespace Natron{
    void debugImage(Natron::Image* img,const QString& filename){
        const RectI& rod = img->getRoD();
        QImage output(rod.width(),rod.height(),QImage::Format_ARGB32);
        const Natron::Color::Lut* lut = Natron::Color::LutManager::sRGBLut();
        lut->to_byte_packed(output.bits(), img->pixelAt(0, 0), rod, rod, rod,
                            Natron::Color::PACKING_RGBA,Natron::Color::PACKING_BGRA, true,false);
        U64 hashKey = img->getHashKey();
        QString hashKeyStr = QString::number(hashKey);
        QString realFileName = filename.isEmpty() ? QString(hashKeyStr+".png") : filename;
        output.save(realFileName);
    }

}

<|endoftext|>


<commit_before>#include "MarantzClient.h"

MarantzClientClass MarantzClient;

MarantzClientClass::MarantzClientClass()
{
    _client = EthernetClient();
    _client.setTimeout(500);
}

void MarantzClientClass::init(IPAddress address)
{
    _address = address;
}

void MarantzClientClass::updateStatistics()
{
    _receiverOn = false;
    memset(_receiverInput, 0, RECEIVER_INPUT_MAXLENGTH + 1);
    memset(_receiverChannels, 0, RECEIVER_CHANNELS_MAXLENGTH + 1);

    if (!_client.connected())
    {
        // If something goes awry and the client is still connected,
        // initiating another connection hangs the whole thing.
        if (_client.connect(_address, 80))
        {
            Serial.print("Connected to ");
            Serial.println(IPAddressConverter.toString(_address));
            _client.print("GET ");
            _client.print(MARANTZ_STATUS_PATH);
            _client.println(" HTTP/1.1");
            _client.print("Host: ");
            _client.println(IPAddressConverter.toString(_address));
            _client.println("Connection: close");
            _client.println();
        }
        else
        {
            Serial.print("Unable to connect to receiver at ");
            Serial.println(IPAddressConverter.toString(_address));
            _client.stop();
            _client.flush();
            return;
        }
    }

    bool mute = false;
    float volume = 0.0;
    char elementName[XML_ELEMENT_NAME_LENGTH + 1];
    this->readToContentStart();

    while (strcmp("item", elementName) != 0)
    {
        // Read the opening "item" tag.
        this->readElement(elementName);
    }

    bool finished = false;
    while (!finished && (_client.connected() || _client.available()))
    {
        this->readElement(elementName);
        if (strcmp("ZonePower", elementName) == 0)
        {
            char powerValue[3];
            memset(powerValue, 0, 3);
            this->readValue(powerValue, 2);
            _receiverOn = strcasecmp("ON", powerValue) == 0;
            Serial.print("ZonePower: ");
            Serial.print(powerValue);
            Serial.print(" (");
            Serial.print(_receiverOn);
            Serial.println(")");
        }
        else if (strcmp("InputFuncSelect", elementName) == 0)
        {
            this->readValue(_receiverInput, RECEIVER_INPUT_MAXLENGTH);
            Serial.print("InputFuncSelect: ");
            Serial.println(_receiverInput);
        }
        if (strcmp("selectSurround", elementName) == 0)
        {
            this->readValue(_receiverChannels, RECEIVER_CHANNELS_MAXLENGTH);
            Serial.print("selectSurround: ");
            Serial.println(_receiverChannels);
        }
        if (strcmp("MasterVolume", elementName) == 0)
        {
            char volValue[8];
            memset(volValue, 0, 8);
            this->readValue(volValue, 7);
            volume = float(int(String(volValue).toFloat() * 10) / 10.0);
            Serial.print("MasterVolume: ");
            Serial.print(volValue);
            Serial.print(" (");
            Serial.print(volume);
            Serial.println(")");
        }
        if (strcmp("Mute", elementName) == 0)
        {
            char muteValue[3];
            memset(muteValue, 0, 3);
            this->readValue(muteValue, 2);
            mute = strcasecmp("on", muteValue) == 0;
            Serial.print("Mute: ");
            Serial.print(muteValue);
            Serial.print(" (");
            Serial.print(mute);
            Serial.println(")");
        }
    }

    _client.stop();
    _client.flush();

    if (mute)
    {
        _receiverVolume = "MUTE";
    }
    else
    {
        _receiverVolume = String(volume + 80.0, 1);
    }

    Serial.print("Resolved volume: ");
    Serial.println(_receiverVolume);
    Serial.println("Finished processing XML.");
    Serial.println();
}

void MarantzClientClass::readValue(char *value, int maxlength)
{
    char elementName[XML_ELEMENT_NAME_LENGTH + 1];
    memset(elementName, 0, XML_ELEMENT_NAME_LENGTH + 1);
    while (strcmp("value", elementName) != 0)
    {
        // Read the opening "value" tag.
        this->readElement(elementName);
    }

    int index = 0;
    while ((_client.available() || _client.connected()) && index < maxlength)
    {
        if (_client.available())
        {
            char c = _client.read();
            if (c != '<')
            {
                value[index++] = c;
            }
            else
            {
                break;
            }
        }
    }
}

void MarantzClientClass::readElement(char* name)
{
    bool matchedOpenBracket = false;
    bool readToElementEnd = false;
    int index = 0;

    while (_client.available() || _client.connected())
    {
        if (_client.available())
        {
            char c = _client.read();
            if (c == '<')
            {
                // We hit the beginning of a tag
                // which may be an opener or a closer.
                matchedOpenBracket = true;
                memset(name, 0, XML_ELEMENT_NAME_LENGTH + 1);
                readToElementEnd = false;
                index = 0;
                continue;
            }

            if (!matchedOpenBracket)
            {
                // Read until we make it to an open bracket;
                continue;
            }

            if (c == '/')
            {
                if (index == 0)
                {
                    // This is the first character since reading an open
                    // bracket so this is a closing tag:
                    // </SomeTag>
                    // Reset and read until we get to an open tag.
                    memset(name, 0, XML_ELEMENT_NAME_LENGTH + 1);
                    index = 0;
                    matchedOpenBracket = false;
                }

                // Allow reading to the close bracket.
                continue;
            }

            if (c == ' ')
            {
                // You can't have a space in an element
                // name so let's just enable reading through
                // to the end.
                readToElementEnd = true;
            }

            if (c == '>')
            {
                if (matchedOpenBracket)
                {
                    // This ended an opening tag, so we're done!
                    return;
                }

                // This ended a closing tag, so continue reading
                // until we find a start element.
                continue;
            }

            if (index >= XML_ELEMENT_NAME_LENGTH)
            {
                // We haven't hit the end but we have enough
                // so just keep reading until we hit the end.
                readToElementEnd = true;
            }

            if (readToElementEnd)
            {
                // We need to just get to the closing bracket.
                continue;
            }

            name[index++] = c;
        }
    }
}

void MarantzClientClass::readToContentStart()
{
    while (_client.available() || _client.connected())
    {
        if (_client.available())
        {
            if (_client.read() == '<')
            {
                break;
            }
        }
    }
}

bool MarantzClientClass::isReceiverOn()
{
    return _receiverOn;
}

char* MarantzClientClass::getReceiverInput()
{
    return _receiverInput;
}

char* MarantzClientClass::getReceiverChannels()
{
    return _receiverChannels;
}

String MarantzClientClass::getReceiverVolume()
{
    return _receiverVolume;
}
<commit_msg>Increased timeout to 20s for reading/connecting.<commit_after>#include "MarantzClient.h"

MarantzClientClass MarantzClient;

MarantzClientClass::MarantzClientClass()
{
    _client = EthernetClient();
    _client.setTimeout(20000);
}

void MarantzClientClass::init(IPAddress address)
{
    _address = address;
}

void MarantzClientClass::updateStatistics()
{
    _receiverOn = false;
    memset(_receiverInput, 0, RECEIVER_INPUT_MAXLENGTH + 1);
    memset(_receiverChannels, 0, RECEIVER_CHANNELS_MAXLENGTH + 1);

    if (!_client.connected())
    {
        // If something goes awry and the client is still connected,
        // initiating another connection hangs the whole thing.
        if (_client.connect(_address, 80))
        {
            Serial.print("Connected to ");
            Serial.println(IPAddressConverter.toString(_address));
            _client.print("GET ");
            _client.print(MARANTZ_STATUS_PATH);
            _client.println(" HTTP/1.1");
            _client.print("Host: ");
            _client.println(IPAddressConverter.toString(_address));
            _client.println("Connection: close");
            _client.println();
        }
        else
        {
            Serial.print("Unable to connect to receiver at ");
            Serial.println(IPAddressConverter.toString(_address));
            _client.stop();
            _client.flush();
            return;
        }
    }

    bool mute = false;
    float volume = 0.0;
    char elementName[XML_ELEMENT_NAME_LENGTH + 1];
    this->readToContentStart();

    while (strcmp("item", elementName) != 0)
    {
        // Read the opening "item" tag.
        this->readElement(elementName);
    }

    bool finished = false;
    while (!finished && (_client.connected() || _client.available()))
    {
        this->readElement(elementName);
        if (strcmp("ZonePower", elementName) == 0)
        {
            char powerValue[3];
            memset(powerValue, 0, 3);
            this->readValue(powerValue, 2);
            _receiverOn = strcasecmp("ON", powerValue) == 0;
            Serial.print("ZonePower: ");
            Serial.print(powerValue);
            Serial.print(" (");
            Serial.print(_receiverOn);
            Serial.println(")");
        }
        else if (strcmp("InputFuncSelect", elementName) == 0)
        {
            this->readValue(_receiverInput, RECEIVER_INPUT_MAXLENGTH);
            Serial.print("InputFuncSelect: ");
            Serial.println(_receiverInput);
        }
        if (strcmp("selectSurround", elementName) == 0)
        {
            this->readValue(_receiverChannels, RECEIVER_CHANNELS_MAXLENGTH);
            Serial.print("selectSurround: ");
            Serial.println(_receiverChannels);
        }
        if (strcmp("MasterVolume", elementName) == 0)
        {
            char volValue[8];
            memset(volValue, 0, 8);
            this->readValue(volValue, 7);
            volume = float(int(String(volValue).toFloat() * 10) / 10.0);
            Serial.print("MasterVolume: ");
            Serial.print(volValue);
            Serial.print(" (");
            Serial.print(volume);
            Serial.println(")");
        }
        if (strcmp("Mute", elementName) == 0)
        {
            char muteValue[3];
            memset(muteValue, 0, 3);
            this->readValue(muteValue, 2);
            mute = strcasecmp("on", muteValue) == 0;
            Serial.print("Mute: ");
            Serial.print(muteValue);
            Serial.print(" (");
            Serial.print(mute);
            Serial.println(")");
        }
    }

    _client.stop();
    _client.flush();

    if (mute)
    {
        _receiverVolume = "MUTE";
    }
    else
    {
        _receiverVolume = String(volume + 80.0, 1);
    }

    Serial.print("Resolved volume: ");
    Serial.println(_receiverVolume);
    Serial.println("Finished processing XML.");
    Serial.println();
}

void MarantzClientClass::readValue(char *value, int maxlength)
{
    char elementName[XML_ELEMENT_NAME_LENGTH + 1];
    memset(elementName, 0, XML_ELEMENT_NAME_LENGTH + 1);
    while (strcmp("value", elementName) != 0)
    {
        // Read the opening "value" tag.
        this->readElement(elementName);
    }

    int index = 0;
    while ((_client.available() || _client.connected()) && index < maxlength)
    {
        if (_client.available())
        {
            char c = _client.read();
            if (c != '<')
            {
                value[index++] = c;
            }
            else
            {
                break;
            }
        }
    }
}

void MarantzClientClass::readElement(char* name)
{
    bool matchedOpenBracket = false;
    bool readToElementEnd = false;
    int index = 0;

    while (_client.available() || _client.connected())
    {
        if (_client.available())
        {
            char c = _client.read();
            if (c == '<')
            {
                // We hit the beginning of a tag
                // which may be an opener or a closer.
                matchedOpenBracket = true;
                memset(name, 0, XML_ELEMENT_NAME_LENGTH + 1);
                readToElementEnd = false;
                index = 0;
                continue;
            }

            if (!matchedOpenBracket)
            {
                // Read until we make it to an open bracket;
                continue;
            }

            if (c == '/')
            {
                if (index == 0)
                {
                    // This is the first character since reading an open
                    // bracket so this is a closing tag:
                    // </SomeTag>
                    // Reset and read until we get to an open tag.
                    memset(name, 0, XML_ELEMENT_NAME_LENGTH + 1);
                    index = 0;
                    matchedOpenBracket = false;
                }

                // Allow reading to the close bracket.
                continue;
            }

            if (c == ' ')
            {
                // You can't have a space in an element
                // name so let's just enable reading through
                // to the end.
                readToElementEnd = true;
            }

            if (c == '>')
            {
                if (matchedOpenBracket)
                {
                    // This ended an opening tag, so we're done!
                    return;
                }

                // This ended a closing tag, so continue reading
                // until we find a start element.
                continue;
            }

            if (index >= XML_ELEMENT_NAME_LENGTH)
            {
                // We haven't hit the end but we have enough
                // so just keep reading until we hit the end.
                readToElementEnd = true;
            }

            if (readToElementEnd)
            {
                // We need to just get to the closing bracket.
                continue;
            }

            name[index++] = c;
        }
    }
}

void MarantzClientClass::readToContentStart()
{
    while (_client.available() || _client.connected())
    {
        if (_client.available())
        {
            if (_client.read() == '<')
            {
                break;
            }
        }
    }
}

bool MarantzClientClass::isReceiverOn()
{
    return _receiverOn;
}

char* MarantzClientClass::getReceiverInput()
{
    return _receiverInput;
}

char* MarantzClientClass::getReceiverChannels()
{
    return _receiverChannels;
}

String MarantzClientClass::getReceiverVolume()
{
    return _receiverVolume;
}
<|endoftext|>


<commit_before>#include <MultiRegions/ExpList1d.h>
#include <LibUtilities/Kernel/kernel.h>

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

	int i,j,e;
	if (argc != 2)
	{
		fprintf(stderr,"Usage: Post-processor meshfile \n");
		exit(1);
	}
	/************************* Mesh File ***********************/
	// Read the mesh
	string fileNameString(argv[1]);
	SpatialDomains::MeshGraph1D mesh;
	// Both the geometry and the expansion information should be read
	mesh.ReadGeometry(fileNameString);
	mesh.ReadExpansions(fileNameString);

	/***********************************************************/

	// Construct an object from the class ExpList1D.
    // This is the class which represents a multi-elemental expansion
	// This object can be constructed based on the input mesh
    MultiRegions::ExpList1DSharedPtr u =
        MemoryManager<MultiRegions::ExpList1D>::AllocateSharedPtr(mesh);

	/***********************************************************/
	// Get the number of elements
	int nelements = u->GetExpSize();
	NekDouble h = 1.0/u->GetExpSize(); // mesh spacing

	// Get the number of modes
	Array<OneD, LibUtilities::BasisSharedPtr>  base = (u->GetExp(0))->GetBase();
	int order = base[0]->GetNumModes();

	/************ Read in the data file and update the coefficients**********/
	// Contains the local polynomial modes for each element
	Array<OneD,NekDouble> uhat_pre = u->UpdateCoeffs();

	ifstream inFile;
	inFile.open("uhatPre.txt");
	double x;
	int index = 0;
	while (inFile >> x)
	{
		uhat_pre[index] = x;
		index++;
	}
	inFile.close();

	/************** Define the kernel object *******************/

	LibUtilities::KernelSharedPtr post_kernel =
		MemoryManager<LibUtilities::Kernel>::AllocateSharedPtr(order);
	post_kernel->UpdateKernelBreaks(h);

	/******************* Post-Processing ***********************/
	// Construct the appropriate post-processed multi-element expansion object
	int post_order = 2*order;
	LibUtilities::PointsType pType = base[0]->GetPointsType();
	LibUtilities::PointsKey  pKey(post_order+1,pType);
	LibUtilities::BasisKey upost_bkey(base[0]->GetBasisType(),post_order,pKey);
	MultiRegions::ExpList1DSharedPtr u_post =
        MemoryManager<MultiRegions::ExpList1D>::AllocateSharedPtr(upost_bkey,mesh);

	// The post-processing for the first element
	// Step1: Define the element ID on which the post-processing is done
	e = 0;

	// Step2: Calculate the points used for evaluating the post-processed solution
	StdRegions::StdExpansionSharedPtr elmExp = u_post->GetExp(e);
	int eval_npoints = elmExp->GetTotPoints();
	Array<OneD,NekDouble> eval_points(eval_npoints);
	elmExp->GetCoords(eval_points);

	// Step3: Call the appropriate post-processing function
	Array<OneD,NekDouble> ustar_elm(eval_npoints);
	u->PostProcess(post_kernel,eval_points,ustar_elm,e,h);

	// The Post-Processing for the entire domain
	// Step1: Calculate the points used for evaluating the post-processed solution
	int eval_npoints2 = u_post->GetNpoints();
	Array<OneD,NekDouble> eval_points2(eval_npoints2);
	u_post->GetCoords(eval_points2);

	// Step2: Call the appropriate post-processing function
	Array<OneD,NekDouble> ustar(eval_npoints2);
	u->PostProcess(post_kernel,eval_points2,ustar,h);

	// Calculate the post-processed coefficients for the entire domain
	Array<OneD,NekDouble> uhat_post = u_post->UpdateCoeffs();
	u_post->FwdTrans(ustar,uhat_post);

	ofstream postCoeff;
	postCoeff.open("postCoeff.txt");
	cout << "Printing the uhat_post: " << endl;  // These coefficients are different than my previous result, given the ustars are the same
	for(e = 0; e < nelements; e++)
	{
		for(j = 0; j < post_order; j++)
		{
			cout << uhat_post[e*post_order+j] << "  ";
			postCoeff << uhat_post[e*post_order+j] << endl;
		}
		cout << endl;
	}

}<commit_msg>Only changed ExpList1d.h to ExpList1D.h<commit_after>#include <MultiRegions/ExpList1D.h>
#include <LibUtilities/Kernel/kernel.h>

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

	int i,j,e;
	if (argc != 2)
	{
		fprintf(stderr,"Usage: Post-processor meshfile \n");
		exit(1);
	}
	/************************* Mesh File ***********************/
	// Read the mesh
	string fileNameString(argv[1]);
	SpatialDomains::MeshGraph1D mesh;
	// Both the geometry and the expansion information should be read
	mesh.ReadGeometry(fileNameString);
	mesh.ReadExpansions(fileNameString);

	/***********************************************************/

	// Construct an object from the class ExpList1D.
    // This is the class which represents a multi-elemental expansion
	// This object can be constructed based on the input mesh
    MultiRegions::ExpList1DSharedPtr u =
        MemoryManager<MultiRegions::ExpList1D>::AllocateSharedPtr(mesh);

	/***********************************************************/
	// Get the number of elements
	int nelements = u->GetExpSize();
	NekDouble h = 1.0/u->GetExpSize(); // mesh spacing

	// Get the number of modes
	Array<OneD, LibUtilities::BasisSharedPtr>  base = (u->GetExp(0))->GetBase();
	int order = base[0]->GetNumModes();

	/************ Read in the data file and update the coefficients**********/
	// Contains the local polynomial modes for each element
	Array<OneD,NekDouble> uhat_pre = u->UpdateCoeffs();

	ifstream inFile;
	inFile.open("uhatPre.txt");
	double x;
	int index = 0;
	while (inFile >> x)
	{
		uhat_pre[index] = x;
		index++;
	}
	inFile.close();

	/************** Define the kernel object *******************/

	LibUtilities::KernelSharedPtr post_kernel =
		MemoryManager<LibUtilities::Kernel>::AllocateSharedPtr(order);
	post_kernel->UpdateKernelBreaks(h);

	/******************* Post-Processing ***********************/
	// Construct the appropriate post-processed multi-element expansion object
	int post_order = 2*order;
	LibUtilities::PointsType pType = base[0]->GetPointsType();
	LibUtilities::PointsKey  pKey(post_order+1,pType);
	LibUtilities::BasisKey upost_bkey(base[0]->GetBasisType(),post_order,pKey);
	MultiRegions::ExpList1DSharedPtr u_post =
        MemoryManager<MultiRegions::ExpList1D>::AllocateSharedPtr(upost_bkey,mesh);

	// The post-processing for the first element
	// Step1: Define the element ID on which the post-processing is done
	e = 0;

	// Step2: Calculate the points used for evaluating the post-processed solution
	StdRegions::StdExpansionSharedPtr elmExp = u_post->GetExp(e);
	int eval_npoints = elmExp->GetTotPoints();
	Array<OneD,NekDouble> eval_points(eval_npoints);
	elmExp->GetCoords(eval_points);

	// Step3: Call the appropriate post-processing function
	Array<OneD,NekDouble> ustar_elm(eval_npoints);
	u->PostProcess(post_kernel,eval_points,ustar_elm,e,h);

	// The Post-Processing for the entire domain
	// Step1: Calculate the points used for evaluating the post-processed solution
	int eval_npoints2 = u_post->GetNpoints();
	Array<OneD,NekDouble> eval_points2(eval_npoints2);
	u_post->GetCoords(eval_points2);

	// Step2: Call the appropriate post-processing function
	Array<OneD,NekDouble> ustar(eval_npoints2);
	u->PostProcess(post_kernel,eval_points2,ustar,h);

	// Calculate the post-processed coefficients for the entire domain
	Array<OneD,NekDouble> uhat_post = u_post->UpdateCoeffs();
	u_post->FwdTrans(ustar,uhat_post);

	ofstream postCoeff;
	postCoeff.open("postCoeff.txt");
	cout << "Printing the uhat_post: " << endl;  // These coefficients are different than my previous result, given the ustars are the same
	for(e = 0; e < nelements; e++)
	{
		for(j = 0; j < post_order; j++)
		{
			cout << uhat_post[e*post_order+j] << "  ";
			postCoeff << uhat_post[e*post_order+j] << endl;
		}
		cout << endl;
	}

}
<|endoftext|>


<commit_before>//===-- TargetData.cpp - Data size & alignment routines --------------------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target properties related to datatype size/offset/alignment
// information.
//
// This structure should be created once, filled in if the defaults are not
// correct and then passed around by const&.  None of the members functions
// require modification to the object.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetData.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
using namespace llvm;

// Handle the Pass registration stuff necessary to use TargetData's.
namespace {
  // Register the default SparcV9 implementation...
  RegisterPass<TargetData> X("targetdata", "Target Data Layout");
}

static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
                               uint64_t &Size, unsigned char &Alignment);

//===----------------------------------------------------------------------===//
// Support for StructLayout
//===----------------------------------------------------------------------===//

StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
  StructAlignment = 0;
  StructSize = 0;

  // Loop over each of the elements, placing them in memory...
  for (StructType::element_iterator TI = ST->element_begin(),
         TE = ST->element_end(); TI != TE; ++TI) {
    const Type *Ty = *TI;
    unsigned char A;
    unsigned TyAlign;
    uint64_t TySize;
    getTypeInfo(Ty, &TD, TySize, A);
    TyAlign = A;

    // Add padding if necessary to make the data element aligned properly...
    if (StructSize % TyAlign != 0)
      StructSize = (StructSize/TyAlign + 1) * TyAlign;   // Add padding...

    // Keep track of maximum alignment constraint
    StructAlignment = std::max(TyAlign, StructAlignment);

    MemberOffsets.push_back(StructSize);
    StructSize += TySize;                 // Consume space for this data item
  }

  // Empty structures have alignment of 1 byte.
  if (StructAlignment == 0) StructAlignment = 1;

  // Add padding to the end of the struct so that it could be put in an array
  // and all array elements would be aligned correctly.
  if (StructSize % StructAlignment != 0)
    StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
}

/// getElementContainingOffset - Given a valid offset into the structure,
/// return the structure index that contains it.
unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
  std::vector<uint64_t>::const_iterator SI =
    std::upper_bound(MemberOffsets.begin(), MemberOffsets.end(),
                     Offset);
  assert(SI != MemberOffsets.begin() && "Offset not in structure type!");
  --SI;
  assert(*SI <= Offset && "upper_bound didn't work");
  assert((SI == MemberOffsets.begin() || *(SI-1) < Offset) &&
         (SI+1 == MemberOffsets.end() || *(SI+1) > Offset) &&
         "Upper bound didn't work!");
  return SI-MemberOffsets.begin();
}

//===----------------------------------------------------------------------===//
//                       TargetData Class Implementation
//===----------------------------------------------------------------------===//

TargetData::TargetData(const std::string &TargetName,
                       bool isLittleEndian, unsigned char PtrSize,
                       unsigned char PtrAl, unsigned char DoubleAl,
                       unsigned char FloatAl, unsigned char LongAl,
                       unsigned char IntAl, unsigned char ShortAl,
                       unsigned char ByteAl, unsigned char BoolAl) {

  // If this assert triggers, a pass "required" TargetData information, but the
  // top level tool did not provide one for it.  We do not want to default
  // construct, or else we might end up using a bad endianness or pointer size!
  //
  assert(!TargetName.empty() &&
         "ERROR: Tool did not specify a target data to use!");

  LittleEndian     = isLittleEndian;
  PointerSize      = PtrSize;
  PointerAlignment = PtrAl;
  DoubleAlignment  = DoubleAl;
  FloatAlignment   = FloatAl;
  LongAlignment    = LongAl;
  IntAlignment     = IntAl;
  ShortAlignment   = ShortAl;
  ByteAlignment    = ByteAl;
  BoolAlignment    = BoolAl;
}

TargetData::TargetData(const std::string &ToolName, const Module *M) {
  LittleEndian     = M->getEndianness() != Module::BigEndian;
  PointerSize      = M->getPointerSize() != Module::Pointer64 ? 4 : 8;
  PointerAlignment = PointerSize;
  DoubleAlignment  = PointerSize;
  FloatAlignment   = 4;
  LongAlignment    = PointerSize;
  IntAlignment     = 4;
  ShortAlignment   = 2;
  ByteAlignment    = 1;
  BoolAlignment    = 1;
}

/// Layouts - The lazy cache of structure layout information maintained by
/// TargetData.
///
static std::map<std::pair<const TargetData*,const StructType*>,
                StructLayout> *Layouts = 0;

TargetData::~TargetData() {
  if (Layouts) {
    // Remove any layouts for this TD.
    std::map<std::pair<const TargetData*,
      const StructType*>, StructLayout>::iterator
      I = Layouts->lower_bound(std::make_pair(this, (const StructType*)0));
    while (I != Layouts->end() && I->first.first == this)
      Layouts->erase(I++);
    if (Layouts->empty()) {
      delete Layouts;
      Layouts = 0;
    }
  }
}

const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
  if (Layouts == 0)
    Layouts = new std::map<std::pair<const TargetData*,const StructType*>,
                           StructLayout>();
  std::map<std::pair<const TargetData*,const StructType*>,
                     StructLayout>::iterator
    I = Layouts->lower_bound(std::make_pair(this, Ty));
  if (I != Layouts->end() && I->first.first == this && I->first.second == Ty)
    return &I->second;
  else {
    return &Layouts->insert(I, std::make_pair(std::make_pair(this, Ty),
                                              StructLayout(Ty, *this)))->second;
  }
}

/// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout
/// objects.  If a TargetData object is alive when types are being refined and
/// removed, this method must be called whenever a StructType is removed to
/// avoid a dangling pointer in this cache.
void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const {
  if (!Layouts) return;  // No cache.

  std::map<std::pair<const TargetData*,const StructType*>,
           StructLayout>::iterator I = Layouts->find(std::make_pair(this, Ty));
  if (I != Layouts->end())
    Layouts->erase(I);
}

static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
                               uint64_t &Size, unsigned char &Alignment) {
  assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
  switch (Ty->getTypeID()) {
  case Type::BoolTyID:   Size = 1; Alignment = TD->getBoolAlignment(); return;
  case Type::VoidTyID:
  case Type::UByteTyID:
  case Type::SByteTyID:  Size = 1; Alignment = TD->getByteAlignment(); return;
  case Type::UShortTyID:
  case Type::ShortTyID:  Size = 2; Alignment = TD->getShortAlignment(); return;
  case Type::UIntTyID:
  case Type::IntTyID:    Size = 4; Alignment = TD->getIntAlignment(); return;
  case Type::ULongTyID:
  case Type::LongTyID:   Size = 8; Alignment = TD->getLongAlignment(); return;
  case Type::FloatTyID:  Size = 4; Alignment = TD->getFloatAlignment(); return;
  case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
  case Type::LabelTyID:
  case Type::PointerTyID:
    Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
    return;
  case Type::ArrayTyID: {
    const ArrayType *ATy = cast<ArrayType>(Ty);
    getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
    unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
    Size = AlignedSize*ATy->getNumElements();
    return;
  }
  case Type::PackedTyID: {
    const PackedType *PTy = cast<PackedType>(Ty);
    getTypeInfo(PTy->getElementType(), TD, Size, Alignment);
    unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
    Size = AlignedSize*PTy->getNumElements();
    return;
  }
  case Type::StructTyID: {
    // Get the layout annotation... which is lazily created on demand.
    const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty));
    Size = Layout->StructSize; Alignment = Layout->StructAlignment;
    return;
  }

  default:
    assert(0 && "Bad type for getTypeInfo!!!");
    return;
  }
}

uint64_t TargetData::getTypeSize(const Type *Ty) const {
  uint64_t Size;
  unsigned char Align;
  getTypeInfo(Ty, this, Size, Align);
  return Size;
}

unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
  uint64_t Size;
  unsigned char Align;
  getTypeInfo(Ty, this, Size, Align);
  return Align;
}

unsigned char TargetData::getTypeAlignmentShift(const Type *Ty) const {
  unsigned Align = getTypeAlignment(Ty);
  assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
  return Log2_32(Align);
}

/// getIntPtrType - Return an unsigned integer type that is the same size or
/// greater to the host pointer size.
const Type *TargetData::getIntPtrType() const {
  switch (getPointerSize()) {
  default: assert(0 && "Unknown pointer size!");
  case 2: return Type::UShortTy;
  case 4: return Type::UIntTy;
  case 8: return Type::ULongTy;
  }
}

uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
                                      const std::vector<Value*> &Idx) const {
  const Type *Ty = ptrTy;
  assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
  uint64_t Result = 0;

  generic_gep_type_iterator<std::vector<Value*>::const_iterator>
    TI = gep_type_begin(ptrTy, Idx.begin(), Idx.end());
  for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX, ++TI) {
    if (const StructType *STy = dyn_cast<StructType>(*TI)) {
      assert(Idx[CurIDX]->getType() == Type::UIntTy && "Illegal struct idx");
      unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();

      // Get structure layout information...
      const StructLayout *Layout = getStructLayout(STy);

      // Add in the offset, as calculated by the structure layout info...
      assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
      Result += Layout->MemberOffsets[FieldNo];

      // Update Ty to refer to current element
      Ty = STy->getElementType(FieldNo);
    } else {
      // Update Ty to refer to current element
      Ty = cast<SequentialType>(Ty)->getElementType();

      // Get the array index and the size of each array element.
      int64_t arrayIdx = cast<ConstantInt>(Idx[CurIDX])->getRawValue();
      Result += arrayIdx * (int64_t)getTypeSize(Ty);
    }
  }

  return Result;
}

<commit_msg>TargetData.cpp::getTypeInfo() was returning alignment of element type as the alignment of a packed type. This is obviously wrong. Added a workaround that returns the size of the packed type as its alignment. The correct fix would be to return a target dependent alignment value provided via TargetLowering (or some other interface).<commit_after>//===-- TargetData.cpp - Data size & alignment routines --------------------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target properties related to datatype size/offset/alignment
// information.
//
// This structure should be created once, filled in if the defaults are not
// correct and then passed around by const&.  None of the members functions
// require modification to the object.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetData.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
using namespace llvm;

// Handle the Pass registration stuff necessary to use TargetData's.
namespace {
  // Register the default SparcV9 implementation...
  RegisterPass<TargetData> X("targetdata", "Target Data Layout");
}

static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
                               uint64_t &Size, unsigned char &Alignment);

//===----------------------------------------------------------------------===//
// Support for StructLayout
//===----------------------------------------------------------------------===//

StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
  StructAlignment = 0;
  StructSize = 0;

  // Loop over each of the elements, placing them in memory...
  for (StructType::element_iterator TI = ST->element_begin(),
         TE = ST->element_end(); TI != TE; ++TI) {
    const Type *Ty = *TI;
    unsigned char A;
    unsigned TyAlign;
    uint64_t TySize;
    getTypeInfo(Ty, &TD, TySize, A);
    TyAlign = A;

    // Add padding if necessary to make the data element aligned properly...
    if (StructSize % TyAlign != 0)
      StructSize = (StructSize/TyAlign + 1) * TyAlign;   // Add padding...

    // Keep track of maximum alignment constraint
    StructAlignment = std::max(TyAlign, StructAlignment);

    MemberOffsets.push_back(StructSize);
    StructSize += TySize;                 // Consume space for this data item
  }

  // Empty structures have alignment of 1 byte.
  if (StructAlignment == 0) StructAlignment = 1;

  // Add padding to the end of the struct so that it could be put in an array
  // and all array elements would be aligned correctly.
  if (StructSize % StructAlignment != 0)
    StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
}

/// getElementContainingOffset - Given a valid offset into the structure,
/// return the structure index that contains it.
unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
  std::vector<uint64_t>::const_iterator SI =
    std::upper_bound(MemberOffsets.begin(), MemberOffsets.end(),
                     Offset);
  assert(SI != MemberOffsets.begin() && "Offset not in structure type!");
  --SI;
  assert(*SI <= Offset && "upper_bound didn't work");
  assert((SI == MemberOffsets.begin() || *(SI-1) < Offset) &&
         (SI+1 == MemberOffsets.end() || *(SI+1) > Offset) &&
         "Upper bound didn't work!");
  return SI-MemberOffsets.begin();
}

//===----------------------------------------------------------------------===//
//                       TargetData Class Implementation
//===----------------------------------------------------------------------===//

TargetData::TargetData(const std::string &TargetName,
                       bool isLittleEndian, unsigned char PtrSize,
                       unsigned char PtrAl, unsigned char DoubleAl,
                       unsigned char FloatAl, unsigned char LongAl,
                       unsigned char IntAl, unsigned char ShortAl,
                       unsigned char ByteAl, unsigned char BoolAl) {

  // If this assert triggers, a pass "required" TargetData information, but the
  // top level tool did not provide one for it.  We do not want to default
  // construct, or else we might end up using a bad endianness or pointer size!
  //
  assert(!TargetName.empty() &&
         "ERROR: Tool did not specify a target data to use!");

  LittleEndian     = isLittleEndian;
  PointerSize      = PtrSize;
  PointerAlignment = PtrAl;
  DoubleAlignment  = DoubleAl;
  FloatAlignment   = FloatAl;
  LongAlignment    = LongAl;
  IntAlignment     = IntAl;
  ShortAlignment   = ShortAl;
  ByteAlignment    = ByteAl;
  BoolAlignment    = BoolAl;
}

TargetData::TargetData(const std::string &ToolName, const Module *M) {
  LittleEndian     = M->getEndianness() != Module::BigEndian;
  PointerSize      = M->getPointerSize() != Module::Pointer64 ? 4 : 8;
  PointerAlignment = PointerSize;
  DoubleAlignment  = PointerSize;
  FloatAlignment   = 4;
  LongAlignment    = PointerSize;
  IntAlignment     = 4;
  ShortAlignment   = 2;
  ByteAlignment    = 1;
  BoolAlignment    = 1;
}

/// Layouts - The lazy cache of structure layout information maintained by
/// TargetData.
///
static std::map<std::pair<const TargetData*,const StructType*>,
                StructLayout> *Layouts = 0;

TargetData::~TargetData() {
  if (Layouts) {
    // Remove any layouts for this TD.
    std::map<std::pair<const TargetData*,
      const StructType*>, StructLayout>::iterator
      I = Layouts->lower_bound(std::make_pair(this, (const StructType*)0));
    while (I != Layouts->end() && I->first.first == this)
      Layouts->erase(I++);
    if (Layouts->empty()) {
      delete Layouts;
      Layouts = 0;
    }
  }
}

const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
  if (Layouts == 0)
    Layouts = new std::map<std::pair<const TargetData*,const StructType*>,
                           StructLayout>();
  std::map<std::pair<const TargetData*,const StructType*>,
                     StructLayout>::iterator
    I = Layouts->lower_bound(std::make_pair(this, Ty));
  if (I != Layouts->end() && I->first.first == this && I->first.second == Ty)
    return &I->second;
  else {
    return &Layouts->insert(I, std::make_pair(std::make_pair(this, Ty),
                                              StructLayout(Ty, *this)))->second;
  }
}

/// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout
/// objects.  If a TargetData object is alive when types are being refined and
/// removed, this method must be called whenever a StructType is removed to
/// avoid a dangling pointer in this cache.
void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const {
  if (!Layouts) return;  // No cache.

  std::map<std::pair<const TargetData*,const StructType*>,
           StructLayout>::iterator I = Layouts->find(std::make_pair(this, Ty));
  if (I != Layouts->end())
    Layouts->erase(I);
}

static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
                               uint64_t &Size, unsigned char &Alignment) {
  assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
  switch (Ty->getTypeID()) {
  case Type::BoolTyID:   Size = 1; Alignment = TD->getBoolAlignment(); return;
  case Type::VoidTyID:
  case Type::UByteTyID:
  case Type::SByteTyID:  Size = 1; Alignment = TD->getByteAlignment(); return;
  case Type::UShortTyID:
  case Type::ShortTyID:  Size = 2; Alignment = TD->getShortAlignment(); return;
  case Type::UIntTyID:
  case Type::IntTyID:    Size = 4; Alignment = TD->getIntAlignment(); return;
  case Type::ULongTyID:
  case Type::LongTyID:   Size = 8; Alignment = TD->getLongAlignment(); return;
  case Type::FloatTyID:  Size = 4; Alignment = TD->getFloatAlignment(); return;
  case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
  case Type::LabelTyID:
  case Type::PointerTyID:
    Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
    return;
  case Type::ArrayTyID: {
    const ArrayType *ATy = cast<ArrayType>(Ty);
    getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
    unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
    Size = AlignedSize*ATy->getNumElements();
    return;
  }
  case Type::PackedTyID: {
    const PackedType *PTy = cast<PackedType>(Ty);
    getTypeInfo(PTy->getElementType(), TD, Size, Alignment);
    unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
    Size = AlignedSize*PTy->getNumElements();
    // FIXME: The alignments of specific packed types are target dependent.
    // For now, just set it to be equal to Size.
    Alignment = Size;
    return;
  }
  case Type::StructTyID: {
    // Get the layout annotation... which is lazily created on demand.
    const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty));
    Size = Layout->StructSize; Alignment = Layout->StructAlignment;
    return;
  }

  default:
    assert(0 && "Bad type for getTypeInfo!!!");
    return;
  }
}

uint64_t TargetData::getTypeSize(const Type *Ty) const {
  uint64_t Size;
  unsigned char Align;
  getTypeInfo(Ty, this, Size, Align);
  return Size;
}

unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
  uint64_t Size;
  unsigned char Align;
  getTypeInfo(Ty, this, Size, Align);
  return Align;
}

unsigned char TargetData::getTypeAlignmentShift(const Type *Ty) const {
  unsigned Align = getTypeAlignment(Ty);
  assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
  return Log2_32(Align);
}

/// getIntPtrType - Return an unsigned integer type that is the same size or
/// greater to the host pointer size.
const Type *TargetData::getIntPtrType() const {
  switch (getPointerSize()) {
  default: assert(0 && "Unknown pointer size!");
  case 2: return Type::UShortTy;
  case 4: return Type::UIntTy;
  case 8: return Type::ULongTy;
  }
}

uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
                                      const std::vector<Value*> &Idx) const {
  const Type *Ty = ptrTy;
  assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
  uint64_t Result = 0;

  generic_gep_type_iterator<std::vector<Value*>::const_iterator>
    TI = gep_type_begin(ptrTy, Idx.begin(), Idx.end());
  for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX, ++TI) {
    if (const StructType *STy = dyn_cast<StructType>(*TI)) {
      assert(Idx[CurIDX]->getType() == Type::UIntTy && "Illegal struct idx");
      unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();

      // Get structure layout information...
      const StructLayout *Layout = getStructLayout(STy);

      // Add in the offset, as calculated by the structure layout info...
      assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
      Result += Layout->MemberOffsets[FieldNo];

      // Update Ty to refer to current element
      Ty = STy->getElementType(FieldNo);
    } else {
      // Update Ty to refer to current element
      Ty = cast<SequentialType>(Ty)->getElementType();

      // Get the array index and the size of each array element.
      int64_t arrayIdx = cast<ConstantInt>(Idx[CurIDX])->getRawValue();
      Result += arrayIdx * (int64_t)getTypeSize(Ty);
    }
  }

  return Result;
}

<|endoftext|>