<commit_before>//
//  lr_parser_stage.cpp
//  Parse
//
//  Created by Andrew Hunter on 27/08/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <sstream>
#include "TameParse/Compiler/lr_parser_stage.h"
#include "TameParse/Lr/conflict.h"
#include "TameParse/Lr/ignored_symbols.h"
#include "TameParse/Language/formatter.h"
#include "TameParse/Lr/ast_parser.h"

using namespace std;
using namespace dfa;
using namespace contextfree;
using namespace lr;
using namespace language;
using namespace compiler;

/// \brief Constructor
lr_parser_stage::lr_parser_stage(console_container& console, const std::wstring& filename, language_stage* languageCompiler, lexer_stage* lexerCompiler, const vector<wstring>& startSymbols)
: compilation_stage(console, filename)
, m_Language(languageCompiler)
, m_LexerCompiler(lexerCompiler)
, m_StartSymbols(startSymbols)
, m_StartPosition(position(-1,-1,-1))
, m_Parser(NULL)
, m_Tables(NULL) {
	// Add empty positions for each symbol
	for (size_t x=0; x<m_StartSymbols.size(); x++) {
		m_SymbolStartPosition.push_back(position(-1,-1,-1));
	}
}

/// \brief Constructure which builds the list of start symbols from a parser block
lr_parser_stage::lr_parser_stage(console_container& console, const std::wstring& filename, language_stage* languageCompiler, lexer_stage* lexerCompiler, parser_block* parserBlock)
: compilation_stage(console, filename)
, m_Language(languageCompiler)
, m_LexerCompiler(lexerCompiler)
, m_StartPosition(parserBlock->start_pos())
, m_StartSymbols(parserBlock->start_symbols())
, m_Parser(NULL)
, m_Tables(NULL) {
	// Make all the symbols begin in the same place as this block
	// TODO: actually record where the symbols are specified
	for (size_t x=0; x<m_StartSymbols.size(); x++) {
		m_SymbolStartPosition.push_back(m_StartPosition);
	}
}

/// \brief Destructor
lr_parser_stage::~lr_parser_stage() {
	// Finished with the parser
	if (m_Parser) {
		delete m_Parser;
		m_Parser = NULL;
	}

    if (m_Tables) {
        delete m_Tables;
        m_Tables = NULL;
    }
}

/// \brief Compiles the parser specified by the parameters to this stage
void lr_parser_stage::compile() {
    // Verbose message to say which stage we're at
	cons().verbose_stream() << L"  = Building parser" << endl;

	// Recycle the parser generator if it already exists
	if (m_Parser) {
		delete m_Parser;
		m_Parser = NULL;
	}

    if (m_Tables) {
        delete m_Tables;
        m_Tables = NULL;
    }

	// Sanity check (language)
	if (!m_Language) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE", L"Language compiler stage was not supplied to parser stage", m_StartPosition));
		return;
	}

	if (!m_Language->ndfa()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE_NDFA", L"Language compiler stage has not generated a lexer", m_StartPosition));
		return;
	}

	if (!m_Language->terminals()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE_TERMINALS", L"Language compiler stage has not generated a terminal dictionary", m_StartPosition));
		return;
	}

	if (!m_Language->weak_symbols()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE_WEAK_SYMBOLS", L"Language compiler stage has not the set of weak symbols", m_StartPosition));
		return;
	}

	if (!m_Language->ignored_symbols()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE_IGNORE_SYMBOLS", L"Language compiler stage has not generated the set of ignore symbols", m_StartPosition));
	}

	if (!m_Language->grammar()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE_GRAMMAR", L"Language compiler stage has not generated a grammar", m_StartPosition));
		return;
	}

	// Sanity check (lexer)
	if (!m_LexerCompiler) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LEXER", L"Lexer compiler stage was not supplied to parser stage", m_StartPosition));
		return;
	}

	if (!m_LexerCompiler->dfa()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LEXER_DFA", L"Lexer compiler stage has not generate a DFA", m_StartPosition));
		return;
	}

	if (!m_LexerCompiler->weak_symbols()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LEXER_DFA", L"Lexer compiler stage has not generate a weak symbols rewriter", m_StartPosition));
		return;
	}

	// Create a new parser builder
	m_Parser = new lalr_builder(*m_Language->grammar(), *m_Language->terminals());

	// Get the nonterminal items corresponding to the start symbols
	vector<item_container> startItems;

	for (size_t startSymbolId = 0; startSymbolId < m_StartSymbols.size(); startSymbolId++) {
		// Get the symbol
		const wstring& startSymbol = m_StartSymbols[startSymbolId];

		// Find the nonterminal item corresponding to this symbol
		if (!m_Language->grammar()->nonterminal_is_defined(startSymbol)) {
			// Report an error if this nonterminal is not defined
			wstringstream msg;
			msg << L"Start symbol is not defined: " << startSymbol;

			cons().report_error(error(error::sev_error, filename(), L"UNDEFINED_NONTERMINAL", msg.str(), m_SymbolStartPosition[startSymbolId]));
			continue;
		}

		// Add to the list of start items
		startItems.push_back(m_Language->grammar()->get_nonterminal(startSymbol));
	}

	// Give up if there are no symbols defined
	if (startItems.empty()) {
		cons().report_error(error(error::sev_error, filename(), L"NO_START_SYMBOLS", L"No start symbols are defined", m_StartPosition));
		return;
	}

    // Generate the ignore actions
    ignored_symbols* ignored = new ignored_symbols();
    action_rewriter_container ignoreContainer(ignored, true);

    for (set<int>::iterator ignoredTerminalId = m_Language->ignored_symbols()->begin(); ignoredTerminalId != m_Language->ignored_symbols()->end(); ignoredTerminalId++) {
        ignored->add_item(terminal(*ignoredTerminalId));
    }

	// Add the initial states to the LALR builder
	m_InitialStates.clear();
	for (vector<item_container>::iterator initialItem = startItems.begin(); initialItem != startItems.end(); initialItem++) {
		m_InitialStates.push_back(m_Parser->add_initial_state(*initialItem));
	}

    // Add the weak symbols and ignore items actions
    // TODO: it might be good to have a way to supply extra rewriters from other stages instead of just having them
    // hardcoded here. This is good enough for now, though.
    m_Parser->add_rewriter(action_rewriter_container(m_LexerCompiler->weak_symbols(), false));
    m_Parser->add_rewriter(ignoreContainer);

	// Build the parser
	m_Parser->complete_parser();

	// Get any conflicts that might exist
	conflict_list conflictList;
	conflict::find_conflicts(*m_Parser, conflictList);

	// Report the conflicts
	// TODO: make the way that conflicts are reported (warnings or errors) configurable
	error::severity shiftReduceSev 	= error::sev_warning;
	error::severity reduceReduceSev	= error::sev_error;

	for (conflict_list::iterator conflict = conflictList.begin(); conflict != conflictList.end(); conflict++) {
		// We don't understand the conflict type if there are no reduce items
		if ((*conflict)->first_reduce_item() == (*conflict)->last_reduce_item()) {
			cons().report_error(error(error::sev_bug, filename(), L"BUG_CONFLICT_NO_REDUCE", L"Found a conflict with no reduce actions", m_StartPosition));
			continue;
		}

		// Test the type of this conflict
		if ((*conflict)->first_shift_item() != (*conflict)->last_shift_item()) {
			// Shift/reduce conflict: we report the 'shift' part of the conflict as the first line
			for (lr0_item_set::const_iterator shiftItem = (*conflict)->first_shift_item(); shiftItem != (*conflict)->last_shift_item(); shiftItem++) {
				// Start building the message
				wstringstream 	shiftMessage;
				error::severity	sev = shiftReduceSev;

				// Message is different if this is the initial message for this conflict vs a detail message
				if (shiftItem == (*conflict)->first_shift_item()) {
					// Displaying the shift/reduce warning if we're on the first shift item
					shiftMessage << L"Shift/reduce conflict on";
					shiftMessage << L" '" << formatter::to_string(*(*conflict)->token(), *m_Language->grammar(), *m_Language->terminals()) << L"':";
				} else {
					// Displaying additional items
					shiftMessage << L"  in:";
					sev = error::sev_detail;
				}

				// Add the item being shifted
				shiftMessage << L" " << formatter::to_string(**shiftItem, *m_Language->grammar(), *m_Language->terminals());

				// Display the warning/error
				int 		ruleId 	= (*shiftItem)->rule()->identifier(*m_Language->grammar());
				position 	rulePos	= m_Language->rule_definition_pos(ruleId);
				cons().report_error(error(sev, m_Language->filename(), L"CONFLICT_SHIFT_REDUCE", shiftMessage.str(), rulePos));
			}
		}

		// Display the reductions for this conflict
		for (conflict::reduce_iterator reduceItem = (*conflict)->first_reduce_item(); reduceItem != (*conflict)->last_reduce_item(); reduceItem++) {
			// Start building the message
			wstring         reduceCode      = L"DETAIL_REDUCE";
			error::severity reductionSev    = error::sev_detail;
			wstringstream	reduceMessage;

            // This is a reduce/reduce conflict if this is the first conflict in the list (ie, no other shift or reduce items)
			if (reduceItem == (*conflict)->first_reduce_item() && (*conflict)->first_shift_item() == (*conflict)->last_shift_item()) {
				// This is a reduce/reduce conflict
				reductionSev = reduceReduceSev;
				reduceCode = L"CONFLICT_REDUCE_REDUCE";
				reduceMessage << L"Reduce/reduce conflict on";
				reduceMessage << L" '" << formatter::to_string(*(*conflict)->token(), *m_Language->grammar(), *m_Language->terminals()) << L"':";
			} else {
				// Displaying additional items
				reduceMessage << L"or reduce:";
			}

			// Add the item being reduced
			reduceMessage << L" " << formatter::to_string(*reduceItem->first->rule(), *m_Language->grammar(), *m_Language->terminals());

			// Display the message for this item
			int 		ruleId 	= reduceItem->first->rule()->identifier(*m_Language->grammar());
			position 	rulePos	= m_Language->rule_definition_pos(ruleId);
			cons().report_error(error(reductionSev, m_Language->filename(), reduceCode, reduceMessage.str(), rulePos));

			// For reduce/reduce conflicts, display the context in which the reduction can occur
            set<item_container> displayedNonterminals;
            report_reduce_conflict(reduceItem, reduceItem->first->rule()->nonterminal(), displayedNonterminals, 0);
		}
	}

    // Build an actual AST parser so we can display some stats
    m_Tables = new parser_tables(*m_Parser, m_LexerCompiler->weak_symbols());

    // Display some stats
    int totalActions = 0;
    for (int stateId = 0; stateId < m_Tables->count_states(); stateId++) {
        totalActions += m_Tables->count_actions_for_state(stateId);
    }

    cons().verbose_stream() << L"    Number of states in the parser:         " << m_Parser->count_states() << endl;
    cons().verbose_stream() << L"    Total number of parse actions:          " << totalActions << endl;
    cons().verbose_stream() << L"    Average number of actions per state:    " << totalActions / m_Tables->count_states() << endl;
    cons().verbose_stream() << L"    Approximate size of final parse tables: " << m_Tables->size()/1024 << L" kilobytes" << endl;
}

/// \brief Reports errors for a particular reduce conflict (the 'in' and 'to' messages)
void lr_parser_stage::report_reduce_conflict(lr::conflict::reduce_iterator& reduceItem, item_container nonterminal, set<item_container>& displayedNonterminals, int level) {
    // Only display the set for a given target nonterminal once
    if (displayedNonterminals.find(nonterminal) != displayedNonterminals.end()) {
        return;
    }

    // Mark this nonterminal as being displayed (so we won't iterate over it)
    displayedNonterminals.insert(nonterminal);

    // For reduce/reduce conflicts, display the context in which the reduction can occur
    for (conflict::possible_reduce_states::const_iterator possibleState = reduceItem->second.begin(); possibleState != reduceItem->second.end(); possibleState++) {
        // Generate a detail message for this item
        const conflict::lr_item_id& itemId = *possibleState;

        // Get the relevant item
        const lr0_item_container& item = (*m_Parser->machine().state_with_id(itemId.first))[itemId.second];

        // Ignore this item if it's not on the correct nonterminal
        if (item->at_end()) continue;
        if (*item->rule()->items()[item->offset()] != *nonterminal) continue;

        // Work out the rule position for this item
        int 		reducedRuleId 	= item->rule()->identifier(*m_Language->grammar());
        position 	reducedRulePos	= m_Language->rule_definition_pos(reducedRuleId);

        // Generate a message
        wstringstream detailMessage;
        detailMessage << wstring((level+1)*2, L' ');
        detailMessage << (level==0?L"in: ":L"to: ");
        detailMessage << formatter::to_string(*item, *m_Language->grammar(), *m_Language->terminals());

        // Write it out
        cons().report_error(error(error::sev_detail, m_Language->filename(), L"DETAIL_REDUCE_IN", detailMessage.str(), reducedRulePos));

        // Display the set for the nonterminals for this rule
        report_reduce_conflict(reduceItem, item->rule()->nonterminal(), displayedNonterminals, level+1);
    }
}
<commit_msg>Added a 'checking for conflicts' message for cases where that's a bit slow<commit_after>//
//  lr_parser_stage.cpp
//  Parse
//
//  Created by Andrew Hunter on 27/08/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <sstream>
#include "TameParse/Compiler/lr_parser_stage.h"
#include "TameParse/Lr/conflict.h"
#include "TameParse/Lr/ignored_symbols.h"
#include "TameParse/Language/formatter.h"
#include "TameParse/Lr/ast_parser.h"

using namespace std;
using namespace dfa;
using namespace contextfree;
using namespace lr;
using namespace language;
using namespace compiler;

/// \brief Constructor
lr_parser_stage::lr_parser_stage(console_container& console, const std::wstring& filename, language_stage* languageCompiler, lexer_stage* lexerCompiler, const vector<wstring>& startSymbols)
: compilation_stage(console, filename)
, m_Language(languageCompiler)
, m_LexerCompiler(lexerCompiler)
, m_StartSymbols(startSymbols)
, m_StartPosition(position(-1,-1,-1))
, m_Parser(NULL)
, m_Tables(NULL) {
	// Add empty positions for each symbol
	for (size_t x=0; x<m_StartSymbols.size(); x++) {
		m_SymbolStartPosition.push_back(position(-1,-1,-1));
	}
}

/// \brief Constructure which builds the list of start symbols from a parser block
lr_parser_stage::lr_parser_stage(console_container& console, const std::wstring& filename, language_stage* languageCompiler, lexer_stage* lexerCompiler, parser_block* parserBlock)
: compilation_stage(console, filename)
, m_Language(languageCompiler)
, m_LexerCompiler(lexerCompiler)
, m_StartPosition(parserBlock->start_pos())
, m_StartSymbols(parserBlock->start_symbols())
, m_Parser(NULL)
, m_Tables(NULL) {
	// Make all the symbols begin in the same place as this block
	// TODO: actually record where the symbols are specified
	for (size_t x=0; x<m_StartSymbols.size(); x++) {
		m_SymbolStartPosition.push_back(m_StartPosition);
	}
}

/// \brief Destructor
lr_parser_stage::~lr_parser_stage() {
	// Finished with the parser
	if (m_Parser) {
		delete m_Parser;
		m_Parser = NULL;
	}

    if (m_Tables) {
        delete m_Tables;
        m_Tables = NULL;
    }
}

/// \brief Compiles the parser specified by the parameters to this stage
void lr_parser_stage::compile() {
    // Verbose message to say which stage we're at
	cons().verbose_stream() << L"  = Building parser" << endl;

	// Recycle the parser generator if it already exists
	if (m_Parser) {
		delete m_Parser;
		m_Parser = NULL;
	}

    if (m_Tables) {
        delete m_Tables;
        m_Tables = NULL;
    }

	// Sanity check (language)
	if (!m_Language) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE", L"Language compiler stage was not supplied to parser stage", m_StartPosition));
		return;
	}

	if (!m_Language->ndfa()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE_NDFA", L"Language compiler stage has not generated a lexer", m_StartPosition));
		return;
	}

	if (!m_Language->terminals()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE_TERMINALS", L"Language compiler stage has not generated a terminal dictionary", m_StartPosition));
		return;
	}

	if (!m_Language->weak_symbols()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE_WEAK_SYMBOLS", L"Language compiler stage has not the set of weak symbols", m_StartPosition));
		return;
	}

	if (!m_Language->ignored_symbols()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE_IGNORE_SYMBOLS", L"Language compiler stage has not generated the set of ignore symbols", m_StartPosition));
	}

	if (!m_Language->grammar()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LANGUAGE_GRAMMAR", L"Language compiler stage has not generated a grammar", m_StartPosition));
		return;
	}

	// Sanity check (lexer)
	if (!m_LexerCompiler) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LEXER", L"Lexer compiler stage was not supplied to parser stage", m_StartPosition));
		return;
	}

	if (!m_LexerCompiler->dfa()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LEXER_DFA", L"Lexer compiler stage has not generate a DFA", m_StartPosition));
		return;
	}

	if (!m_LexerCompiler->weak_symbols()) {
		cons().report_error(error(error::sev_bug, filename(), L"BUG_NO_LEXER_DFA", L"Lexer compiler stage has not generate a weak symbols rewriter", m_StartPosition));
		return;
	}

	// Create a new parser builder
	m_Parser = new lalr_builder(*m_Language->grammar(), *m_Language->terminals());

	// Get the nonterminal items corresponding to the start symbols
	vector<item_container> startItems;

	for (size_t startSymbolId = 0; startSymbolId < m_StartSymbols.size(); startSymbolId++) {
		// Get the symbol
		const wstring& startSymbol = m_StartSymbols[startSymbolId];

		// Find the nonterminal item corresponding to this symbol
		if (!m_Language->grammar()->nonterminal_is_defined(startSymbol)) {
			// Report an error if this nonterminal is not defined
			wstringstream msg;
			msg << L"Start symbol is not defined: " << startSymbol;

			cons().report_error(error(error::sev_error, filename(), L"UNDEFINED_NONTERMINAL", msg.str(), m_SymbolStartPosition[startSymbolId]));
			continue;
		}

		// Add to the list of start items
		startItems.push_back(m_Language->grammar()->get_nonterminal(startSymbol));
	}

	// Give up if there are no symbols defined
	if (startItems.empty()) {
		cons().report_error(error(error::sev_error, filename(), L"NO_START_SYMBOLS", L"No start symbols are defined", m_StartPosition));
		return;
	}

    // Generate the ignore actions
    ignored_symbols* ignored = new ignored_symbols();
    action_rewriter_container ignoreContainer(ignored, true);

    for (set<int>::iterator ignoredTerminalId = m_Language->ignored_symbols()->begin(); ignoredTerminalId != m_Language->ignored_symbols()->end(); ignoredTerminalId++) {
        ignored->add_item(terminal(*ignoredTerminalId));
    }

	// Add the initial states to the LALR builder
	m_InitialStates.clear();
	for (vector<item_container>::iterator initialItem = startItems.begin(); initialItem != startItems.end(); initialItem++) {
		m_InitialStates.push_back(m_Parser->add_initial_state(*initialItem));
	}

    // Add the weak symbols and ignore items actions
    // TODO: it might be good to have a way to supply extra rewriters from other stages instead of just having them
    // hardcoded here. This is good enough for now, though.
    m_Parser->add_rewriter(action_rewriter_container(m_LexerCompiler->weak_symbols(), false));
    m_Parser->add_rewriter(ignoreContainer);

	// Build the parser
	m_Parser->complete_parser();

	// Get any conflicts that might exist
	conflict_list conflictList;
	cons().verbose_stream() << L"  = Checking for conflicts" << endl;
	conflict::find_conflicts(*m_Parser, conflictList);

	// Report the conflicts
	// TODO: make the way that conflicts are reported (warnings or errors) configurable
	error::severity shiftReduceSev 	= error::sev_warning;
	error::severity reduceReduceSev	= error::sev_error;

	for (conflict_list::iterator conflict = conflictList.begin(); conflict != conflictList.end(); conflict++) {
		// We don't understand the conflict type if there are no reduce items
		if ((*conflict)->first_reduce_item() == (*conflict)->last_reduce_item()) {
			cons().report_error(error(error::sev_bug, filename(), L"BUG_CONFLICT_NO_REDUCE", L"Found a conflict with no reduce actions", m_StartPosition));
			continue;
		}

		// Test the type of this conflict
		if ((*conflict)->first_shift_item() != (*conflict)->last_shift_item()) {
			// Shift/reduce conflict: we report the 'shift' part of the conflict as the first line
			for (lr0_item_set::const_iterator shiftItem = (*conflict)->first_shift_item(); shiftItem != (*conflict)->last_shift_item(); shiftItem++) {
				// Start building the message
				wstringstream 	shiftMessage;
				error::severity	sev = shiftReduceSev;

				// Message is different if this is the initial message for this conflict vs a detail message
				if (shiftItem == (*conflict)->first_shift_item()) {
					// Displaying the shift/reduce warning if we're on the first shift item
					shiftMessage << L"Shift/reduce conflict on";
					shiftMessage << L" '" << formatter::to_string(*(*conflict)->token(), *m_Language->grammar(), *m_Language->terminals()) << L"':";
				} else {
					// Displaying additional items
					shiftMessage << L"  in:";
					sev = error::sev_detail;
				}

				// Add the item being shifted
				shiftMessage << L" " << formatter::to_string(**shiftItem, *m_Language->grammar(), *m_Language->terminals());

				// Display the warning/error
				int 		ruleId 	= (*shiftItem)->rule()->identifier(*m_Language->grammar());
				position 	rulePos	= m_Language->rule_definition_pos(ruleId);
				cons().report_error(error(sev, m_Language->filename(), L"CONFLICT_SHIFT_REDUCE", shiftMessage.str(), rulePos));
			}
		}

		// Display the reductions for this conflict
		for (conflict::reduce_iterator reduceItem = (*conflict)->first_reduce_item(); reduceItem != (*conflict)->last_reduce_item(); reduceItem++) {
			// Start building the message
			wstring         reduceCode      = L"DETAIL_REDUCE";
			error::severity reductionSev    = error::sev_detail;
			wstringstream	reduceMessage;

            // This is a reduce/reduce conflict if this is the first conflict in the list (ie, no other shift or reduce items)
			if (reduceItem == (*conflict)->first_reduce_item() && (*conflict)->first_shift_item() == (*conflict)->last_shift_item()) {
				// This is a reduce/reduce conflict
				reductionSev = reduceReduceSev;
				reduceCode = L"CONFLICT_REDUCE_REDUCE";
				reduceMessage << L"Reduce/reduce conflict on";
				reduceMessage << L" '" << formatter::to_string(*(*conflict)->token(), *m_Language->grammar(), *m_Language->terminals()) << L"':";
			} else {
				// Displaying additional items
				reduceMessage << L"or reduce:";
			}

			// Add the item being reduced
			reduceMessage << L" " << formatter::to_string(*reduceItem->first->rule(), *m_Language->grammar(), *m_Language->terminals());

			// Display the message for this item
			int 		ruleId 	= reduceItem->first->rule()->identifier(*m_Language->grammar());
			position 	rulePos	= m_Language->rule_definition_pos(ruleId);
			cons().report_error(error(reductionSev, m_Language->filename(), reduceCode, reduceMessage.str(), rulePos));

			// For reduce/reduce conflicts, display the context in which the reduction can occur
            set<item_container> displayedNonterminals;
            report_reduce_conflict(reduceItem, reduceItem->first->rule()->nonterminal(), displayedNonterminals, 0);
		}
	}

    // Build an actual AST parser so we can display some stats
    m_Tables = new parser_tables(*m_Parser, m_LexerCompiler->weak_symbols());

    // Display some stats
    int totalActions = 0;
    for (int stateId = 0; stateId < m_Tables->count_states(); stateId++) {
        totalActions += m_Tables->count_actions_for_state(stateId);
    }

    cons().verbose_stream() << L"    Number of states in the parser:         " << m_Parser->count_states() << endl;
    cons().verbose_stream() << L"    Total number of parse actions:          " << totalActions << endl;
    cons().verbose_stream() << L"    Average number of actions per state:    " << totalActions / m_Tables->count_states() << endl;
    cons().verbose_stream() << L"    Approximate size of final parse tables: " << m_Tables->size()/1024 << L" kilobytes" << endl;
}

/// \brief Reports errors for a particular reduce conflict (the 'in' and 'to' messages)
void lr_parser_stage::report_reduce_conflict(lr::conflict::reduce_iterator& reduceItem, item_container nonterminal, set<item_container>& displayedNonterminals, int level) {
    // Only display the set for a given target nonterminal once
    if (displayedNonterminals.find(nonterminal) != displayedNonterminals.end()) {
        return;
    }

    // Mark this nonterminal as being displayed (so we won't iterate over it)
    displayedNonterminals.insert(nonterminal);

    // For reduce/reduce conflicts, display the context in which the reduction can occur
    for (conflict::possible_reduce_states::const_iterator possibleState = reduceItem->second.begin(); possibleState != reduceItem->second.end(); possibleState++) {
        // Generate a detail message for this item
        const conflict::lr_item_id& itemId = *possibleState;

        // Get the relevant item
        const lr0_item_container& item = (*m_Parser->machine().state_with_id(itemId.first))[itemId.second];

        // Ignore this item if it's not on the correct nonterminal
        if (item->at_end()) continue;
        if (*item->rule()->items()[item->offset()] != *nonterminal) continue;

        // Work out the rule position for this item
        int 		reducedRuleId 	= item->rule()->identifier(*m_Language->grammar());
        position 	reducedRulePos	= m_Language->rule_definition_pos(reducedRuleId);

        // Generate a message
        wstringstream detailMessage;
        detailMessage << wstring((level+1)*2, L' ');
        detailMessage << (level==0?L"in: ":L"to: ");
        detailMessage << formatter::to_string(*item, *m_Language->grammar(), *m_Language->terminals());

        // Write it out
        cons().report_error(error(error::sev_detail, m_Language->filename(), L"DETAIL_REDUCE_IN", detailMessage.str(), reducedRulePos));

        // Display the set for the nonterminals for this rule
        report_reduce_conflict(reduceItem, item->rule()->nonterminal(), displayedNonterminals, level+1);
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include <SofaSimpleFem/HexahedronFEMForceField.h>
#include <SofaTest/ForceField_test.h>

namespace sofa {

using namespace modeling;

/**  Test suite for HexahedronFEMForceField: we check if the accurate forces are computed
  */
template <typename _HexahedronFEMForceField>
struct HexahedronFEMForceField_test : public ForceField_test<_HexahedronFEMForceField>
{

    typedef _HexahedronFEMForceField ForceType;
    typedef ForceField_test<_HexahedronFEMForceField> Inherited;
    typedef typename ForceType::DataTypes DataTypes;

    typedef typename ForceType::VecCoord VecCoord;
    typedef typename ForceType::VecDeriv VecDeriv;
    typedef typename ForceType::Coord Coord;
    typedef typename ForceType::Deriv Deriv;
    typedef typename Coord::value_type Real;
    typedef helper::Vec<3,Real> Vec3;

    typedef ForceType Spring;
    typedef component::container::MechanicalObject<DataTypes> DOF;

    VecCoord x;
    VecDeriv v,f;

    HexahedronFEMForceField_test():Inherited::ForceField_test(std::string(SOFASIMPLEFEM_TEST_SCENES_DIR) + "/" + "HexahedronFEMForceField.scn")
    {
        //Position
        x.resize(8);
        DataTypes::set( x[0], 0,0,0);
        DataTypes::set( x[1], 1,0,0);
        DataTypes::set( x[2], 1,1,0);
        DataTypes::set( x[3], 0,1,0);
        // Apply an extension along z axis
        Vec3 xTmp(0,1,1.1);
        DataTypes::set( x[4], xTmp[0],xTmp[0],xTmp[2]);
        DataTypes::set( x[5], xTmp[1],xTmp[0],xTmp[2]);
        DataTypes::set( x[6], xTmp[1],xTmp[1],xTmp[2]);
        DataTypes::set( x[7], xTmp[0],xTmp[1],xTmp[2]);
        //Velocity
        v.resize(8);
        DataTypes::set( v[0], 0,0,0);
        DataTypes::set( v[1], 0,0,0);
        DataTypes::set( v[2], 0,0,0);
        DataTypes::set( v[3], 0,0,0);
        DataTypes::set( v[4], 0,0,0);
        DataTypes::set( v[5], 0,0,0);
        DataTypes::set( v[6], 0,0,0);
        DataTypes::set( v[7], 0,0,0);
        //Expected force
        f.resize(8);
        Vec3 fdown(0,0,0.25);
        Vec3 fup(0,0,-0.25);
        DataTypes::set( f[0],  fdown[0], fdown[1], fdown[2]);
        DataTypes::set( f[1],  fdown[0], fdown[1], fdown[2]);
        DataTypes::set( f[2],  fdown[0], fdown[1], fdown[2]);
        DataTypes::set( f[3],  fdown[0], fdown[1], fdown[2]);
        DataTypes::set( f[4],  fup[0], fup[1], fup[2]);
        DataTypes::set( f[5],  fup[0], fup[1], fup[2]);
        DataTypes::set( f[6],  fup[0], fup[1], fup[2]);
        DataTypes::set( f[7],  fup[0], fup[1], fup[2]);

        // Set force parameters
        Inherited::force->f_poissonRatio.setValue(0);
        Inherited::force->f_youngModulus.setValue(10);
        Inherited::force->setMethod(2); // small method
        Inherited::force->isCompliance.setValue(0);

        // Init simulation
        sofa::simulation::getSimulation()->init(Inherited::node.get());

    }

    //Test the value of the force it should be equal for each vertex to Pressure*area/4
    void test_valueForce()
    {
        // run the forcefield_test
        Inherited::run_test( x, v, f );
    }
};

// ========= Define the list of types to instanciate.
//using testing::Types;
typedef testing::Types<
component::forcefield::HexahedronFEMForceField<defaulttype::Vec3Types>
> TestTypes; // the types to instanciate.

// ========= Tests to run for each instanciated type
TYPED_TEST_CASE(HexahedronFEMForceField_test, TestTypes);

// test case
TYPED_TEST( HexahedronFEMForceField_test , extension )
{
    this->errorMax *= 100;
    this->deltaRange = std::make_pair( 1, this->errorMax * 10 );
    this->debug = false;

    // run test
    this->test_valueForce();
}

} // namespace sofa
<commit_msg>[SofaSimpleFem] ADD test for computeBBox<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include <SofaSimpleFem/HexahedronFEMForceField.h>
#include <SofaTest/ForceField_test.h>

namespace sofa {

using namespace modeling;

/**  Test suite for HexahedronFEMForceField: we check if the accurate forces are computed
  */
template <typename _HexahedronFEMForceField>
struct HexahedronFEMForceField_test : public ForceField_test<_HexahedronFEMForceField>
{

    typedef _HexahedronFEMForceField ForceType;
    typedef ForceField_test<_HexahedronFEMForceField> Inherited;
    typedef typename ForceType::DataTypes DataTypes;

    typedef typename ForceType::VecCoord VecCoord;
    typedef typename ForceType::VecDeriv VecDeriv;
    typedef typename ForceType::Coord Coord;
    typedef typename ForceType::Deriv Deriv;
    typedef core::objectmodel::Data<VecCoord> DataVecCoord;
    typedef typename Coord::value_type Real;
    typedef helper::Vec<3,Real> Vec3;

    typedef ForceType Spring;
    typedef component::container::MechanicalObject<DataTypes> DOF;

    VecCoord x;
    VecDeriv v,f;

    HexahedronFEMForceField_test():Inherited::ForceField_test(std::string(SOFASIMPLEFEM_TEST_SCENES_DIR) + "/" + "HexahedronFEMForceField.scn")
    {
        //Position
        x.resize(8);
        DataTypes::set( x[0], 0,0,0);
        DataTypes::set( x[1], 1,0,0);
        DataTypes::set( x[2], 1,1,0);
        DataTypes::set( x[3], 0,1,0);
        // Apply an extension along z axis
        Vec3 xTmp(0,1,1.1);
        DataTypes::set( x[4], xTmp[0],xTmp[0],xTmp[2]);
        DataTypes::set( x[5], xTmp[1],xTmp[0],xTmp[2]);
        DataTypes::set( x[6], xTmp[1],xTmp[1],xTmp[2]);
        DataTypes::set( x[7], xTmp[0],xTmp[1],xTmp[2]);
        //Velocity
        v.resize(8);
        DataTypes::set( v[0], 0,0,0);
        DataTypes::set( v[1], 0,0,0);
        DataTypes::set( v[2], 0,0,0);
        DataTypes::set( v[3], 0,0,0);
        DataTypes::set( v[4], 0,0,0);
        DataTypes::set( v[5], 0,0,0);
        DataTypes::set( v[6], 0,0,0);
        DataTypes::set( v[7], 0,0,0);
        //Expected force
        f.resize(8);
        Vec3 fdown(0,0,0.25);
        Vec3 fup(0,0,-0.25);
        DataTypes::set( f[0],  fdown[0], fdown[1], fdown[2]);
        DataTypes::set( f[1],  fdown[0], fdown[1], fdown[2]);
        DataTypes::set( f[2],  fdown[0], fdown[1], fdown[2]);
        DataTypes::set( f[3],  fdown[0], fdown[1], fdown[2]);
        DataTypes::set( f[4],  fup[0], fup[1], fup[2]);
        DataTypes::set( f[5],  fup[0], fup[1], fup[2]);
        DataTypes::set( f[6],  fup[0], fup[1], fup[2]);
        DataTypes::set( f[7],  fup[0], fup[1], fup[2]);

        // Set force parameters
        Inherited::force->f_poissonRatio.setValue(0);
        Inherited::force->f_youngModulus.setValue(10);
        Inherited::force->setMethod(2); // small method
        Inherited::force->isCompliance.setValue(0);

        // Init simulation
        sofa::simulation::getSimulation()->init(Inherited::node.get());

    }

    //Test the value of the force it should be equal for each vertex to Pressure*area/4
    void test_valueForce()
    {
        // run the forcefield_test
        Inherited::run_test( x, v, f );
    }

    void test_computeBBox()
    {
        std::size_t n = x.size();
        // copy the position and velocities to the scene graph
        this->dof->resize(n);
        typename DOF::WriteVecCoord xdof = this->dof->writePositions();
        copyToData( xdof, x );
        // init scene and compute force
        sofa::simulation::getSimulation()->init(this->node.get());

        Inherited::force->computeBBox(NULL, true);

        EXPECT_EQ(Inherited::force->f_bbox.getValue().minBBox(), Vec3(0,0,0));
        EXPECT_EQ(Inherited::force->f_bbox.getValue().maxBBox(), Vec3(1,1,1.1));
    }
};

// ========= Define the list of types to instanciate.
//using testing::Types;
typedef testing::Types<
component::forcefield::HexahedronFEMForceField<defaulttype::Vec3Types>
> TestTypes; // the types to instanciate.

// ========= Tests to run for each instanciated type
TYPED_TEST_CASE(HexahedronFEMForceField_test, TestTypes);

// test case
TYPED_TEST( HexahedronFEMForceField_test , extension )
{
    this->errorMax *= 100;
    this->deltaRange = std::make_pair( 1, this->errorMax * 10 );
    this->debug = false;

    // run test
    this->test_valueForce();
}

TYPED_TEST( HexahedronFEMForceField_test, test_computeBBox )
{
    ASSERT_NO_THROW(this->test_computeBBox()) ;
}

} // namespace sofa
<|endoftext|>


<commit_before>/*!
	@file
	@author		Albert Semenov
	@date		08/2010
*/
#include "precompiled.h"
#include "SettingsManager.h"

template <> tools::SettingsManager* MyGUI::Singleton<tools::SettingsManager>::msInstance = nullptr;
template <> const char* MyGUI::Singleton<tools::SettingsManager>::mClassTypeName("SettingsManager");

namespace tools
{
	const std::string LogSection = "LayoutEditor";

	const std::wstring settingsFile = L"settings.xml";
	const std::wstring userSettingsFile = L"le_user_settings.xml";
	const size_t MAX_RECENT_FILES = 8;

	SettingsManager::SettingsManager()
	{
	}

	SettingsManager::~SettingsManager()
	{
		destroyAllSectors();
	}

	void SettingsManager::initialise()
	{
		loadSettings(settingsFile, true);
		loadSettings(userSettingsFile, false);
	}

	void SettingsManager::shutdown()
	{
		saveSettings(userSettingsFile);
		destroyAllSectors();
	}

	void SettingsManager::loadSettings(const MyGUI::UString& _fileName, bool _internal)
	{
		std::string _instance = "Editor";

		MyGUI::xml::Document doc;
		if (_internal)
		{
			MyGUI::DataStreamHolder data = MyGUI::DataManager::getInstance().getData(_fileName);
			if (data.getData() != nullptr)
			{
				if (!doc.open(data.getData()))
				{
					MYGUI_LOGGING(LogSection, Error, _instance << " : " << doc.getLastError());
					return;
				}
			}
		}
		else
		{
			if (!doc.open(_fileName))
			{
				MYGUI_LOGGING(LogSection, Error, _instance << " : " << doc.getLastError());
				return;
			}
		}

		MyGUI::xml::ElementPtr root = doc.getRoot();
		if (!root || (root->getName() != "MyGUI"))
		{
			MYGUI_LOGGING(LogSection, Error, _instance << " : '" << _fileName << "', tag 'MyGUI' not found");
			return;
		}

		std::string type;
		if (root->findAttribute("type", type))
		{
			if (type == "Settings")
			{
				//
				MyGUI::xml::ElementEnumerator field = root->getElementEnumerator();
				while (field.next())
				{
					/*if (field->getName() == "PropertiesPanelView") mPropertiesPanelView->load(field);
					else if (field->getName() == "SettingsWindow") mSettingsWindow->load(field);
					else if (field->getName() == "WidgetsWindow") mWidgetsWindow->load(field);
					else if (field->getName() == "MetaSolutionWindow")
					{
						if (isNeedSolutionLoad(field))
						{
							clearWidgetWindow();
							mMetaSolutionWindow->load(field);
						}
					}
					else */if (field->getName() == "RecentFile")
					{
						std::string name;
						if (!field->findAttribute("name", name)) continue;
						addRecentFile(name);
						//mRecentFiles.push_back(name);
					}
					else if (field->getName() == "AdditionalPath")
					{
						std::string name;
						if (!field->findAttribute("name", name)) continue;
						mAdditionalPaths.push_back(name);
					}
					else
					{
						loadSector(field.current());
					}
				}
			}
		}
	}

	void SettingsManager::saveSettings(const MyGUI::UString& _fileName)
	{
		std::string _instance = "Editor";

		MyGUI::xml::Document doc;
		doc.createDeclaration();
		MyGUI::xml::ElementPtr root = doc.createRoot("MyGUI");
		root->addAttribute("type", "Settings");

		saveSectors(root);

		// cleanup for duplicates
		/*std::reverse(mRecentFiles.begin(), mRecentFiles.end());
		for (size_t i = 0; i < mRecentFiles.size(); ++i)
			mRecentFiles.erase(std::remove(mRecentFiles.begin() + i + 1, mRecentFiles.end(), mRecentFiles[i]), mRecentFiles.end());

		// remove old files
		while (mRecentFiles.size() > MAX_RECENT_FILES)
			mRecentFiles.pop_back();
		std::reverse(mRecentFiles.begin(), mRecentFiles.end());*/

		for (std::vector<MyGUI::UString>::iterator iter = mRecentFiles.begin(); iter != mRecentFiles.end(); ++iter)
		{
			MyGUI::xml::ElementPtr nodeProp = root->createChild("RecentFile");
			nodeProp->addAttribute("name", *iter);
		}

		for (std::vector<MyGUI::UString>::iterator iter = mAdditionalPaths.begin(); iter != mAdditionalPaths.end(); ++iter)
		{
			MyGUI::xml::ElementPtr nodeProp = root->createChild("AdditionalPath");
			nodeProp->addAttribute("name", *iter);
		}

		if (!doc.save(_fileName))
		{
			MYGUI_LOGGING(LogSection, Error, _instance << " : " << doc.getLastError());
			return;
		}
	}

	void SettingsManager::addRecentFile(const MyGUI::UString& _fileName)
	{
		VectorUString::iterator item = std::remove(mRecentFiles.begin(), mRecentFiles.end(), _fileName);
		if (item != mRecentFiles.end())
			mRecentFiles.erase(item);

		mRecentFiles.push_back(_fileName);

		while (mRecentFiles.size() > MAX_RECENT_FILES)
			mRecentFiles.erase(mRecentFiles.begin());

		eventSettingsChanged("Main", "RecentFiles");
	}

	void SettingsManager::loadSector(MyGUI::xml::ElementPtr _sectorNode)
	{
		SettingsSector* sector = new SettingsSector();
		sector->eventSettingsChanged = MyGUI::newDelegate(this, &SettingsManager::notifySettingsChanged);

		sector->deserialization(_sectorNode, MyGUI::Version());

		mSettings.push_back(sector);
	}

	void SettingsManager::saveSectors(MyGUI::xml::ElementPtr _rootNode)
	{
		for (VectorSettingsSector::iterator item = mSettings.begin(); item != mSettings.end(); ++item)
			(*item)->serialization(_rootNode, MyGUI::Version());
	}

	void SettingsManager::destroyAllSectors()
	{
		for (VectorSettingsSector::iterator item = mSettings.begin(); item != mSettings.end(); ++item)
			delete (*item);
		mSettings.clear();
	}

	SettingsSector* SettingsManager::getSector(const MyGUI::UString& _sectorName)
	{
		for (VectorSettingsSector::iterator item = mSettings.begin(); item != mSettings.end(); ++item)
		{
			if ((*item)->getName() == _sectorName)
				return (*item);
		}

		SettingsSector* sector = new SettingsSector();
		sector->eventSettingsChanged = MyGUI::newDelegate(this, &SettingsManager::notifySettingsChanged);

		sector->setName(_sectorName);

		mSettings.push_back(sector);
		return sector;
	}

	void SettingsManager::notifySettingsChanged(SettingsSector* _sector, const MyGUI::UString& _propertyName)
	{
		eventSettingsChanged(_sector->getName(), _propertyName);
	}

} // namespace tools
<commit_msg>LE: fix settings<commit_after>/*!
	@file
	@author		Albert Semenov
	@date		08/2010
*/
#include "precompiled.h"
#include "SettingsManager.h"

template <> tools::SettingsManager* MyGUI::Singleton<tools::SettingsManager>::msInstance = nullptr;
template <> const char* MyGUI::Singleton<tools::SettingsManager>::mClassTypeName("SettingsManager");

namespace tools
{
	const std::string LogSection = "LayoutEditor";

	const std::wstring settingsFile = L"settings.xml";
	const std::wstring userSettingsFile = L"le_user_settings.xml";
	const size_t MAX_RECENT_FILES = 8;

	SettingsManager::SettingsManager()
	{
	}

	SettingsManager::~SettingsManager()
	{
		destroyAllSectors();
	}

	void SettingsManager::initialise()
	{
		loadSettings(settingsFile, true);
		loadSettings(userSettingsFile, false);
	}

	void SettingsManager::shutdown()
	{
		saveSettings(userSettingsFile);
		destroyAllSectors();
	}

	void SettingsManager::loadSettings(const MyGUI::UString& _fileName, bool _internal)
	{
		std::string _instance = "Editor";

		MyGUI::xml::Document doc;
		if (_internal)
		{
			MyGUI::DataStreamHolder data = MyGUI::DataManager::getInstance().getData(_fileName);
			if (data.getData() != nullptr)
			{
				if (!doc.open(data.getData()))
				{
					MYGUI_LOGGING(LogSection, Error, _instance << " : " << doc.getLastError());
					return;
				}
			}
		}
		else
		{
			if (!doc.open(_fileName))
			{
				MYGUI_LOGGING(LogSection, Error, _instance << " : " << doc.getLastError());
				return;
			}
		}

		MyGUI::xml::ElementPtr root = doc.getRoot();
		if (!root || (root->getName() != "MyGUI"))
		{
			MYGUI_LOGGING(LogSection, Error, _instance << " : '" << _fileName << "', tag 'MyGUI' not found");
			return;
		}

		std::string type;
		if (root->findAttribute("type", type))
		{
			if (type == "Settings")
			{
				//
				MyGUI::xml::ElementEnumerator field = root->getElementEnumerator();
				while (field.next())
				{
					/*if (field->getName() == "PropertiesPanelView") mPropertiesPanelView->load(field);
					else if (field->getName() == "SettingsWindow") mSettingsWindow->load(field);
					else if (field->getName() == "WidgetsWindow") mWidgetsWindow->load(field);
					else if (field->getName() == "MetaSolutionWindow")
					{
						if (isNeedSolutionLoad(field))
						{
							clearWidgetWindow();
							mMetaSolutionWindow->load(field);
						}
					}
					else */if (field->getName() == "RecentFile")
					{
						std::string name;
						if (!field->findAttribute("name", name)) continue;
						addRecentFile(name);
						//mRecentFiles.push_back(name);
					}
					else if (field->getName() == "AdditionalPath")
					{
						std::string name;
						if (!field->findAttribute("name", name)) continue;
						mAdditionalPaths.push_back(name);
					}
					else
					{
						loadSector(field.current());
					}
				}
			}
		}
	}

	void SettingsManager::saveSettings(const MyGUI::UString& _fileName)
	{
		std::string _instance = "Editor";

		MyGUI::xml::Document doc;
		doc.createDeclaration();
		MyGUI::xml::ElementPtr root = doc.createRoot("MyGUI");
		root->addAttribute("type", "Settings");

		saveSectors(root);

		// cleanup for duplicates
		/*std::reverse(mRecentFiles.begin(), mRecentFiles.end());
		for (size_t i = 0; i < mRecentFiles.size(); ++i)
			mRecentFiles.erase(std::remove(mRecentFiles.begin() + i + 1, mRecentFiles.end(), mRecentFiles[i]), mRecentFiles.end());

		// remove old files
		while (mRecentFiles.size() > MAX_RECENT_FILES)
			mRecentFiles.pop_back();
		std::reverse(mRecentFiles.begin(), mRecentFiles.end());*/

		for (std::vector<MyGUI::UString>::iterator iter = mRecentFiles.begin(); iter != mRecentFiles.end(); ++iter)
		{
			MyGUI::xml::ElementPtr nodeProp = root->createChild("RecentFile");
			nodeProp->addAttribute("name", *iter);
		}

		for (std::vector<MyGUI::UString>::iterator iter = mAdditionalPaths.begin(); iter != mAdditionalPaths.end(); ++iter)
		{
			MyGUI::xml::ElementPtr nodeProp = root->createChild("AdditionalPath");
			nodeProp->addAttribute("name", *iter);
		}

		if (!doc.save(_fileName))
		{
			MYGUI_LOGGING(LogSection, Error, _instance << " : " << doc.getLastError());
			return;
		}
	}

	void SettingsManager::addRecentFile(const MyGUI::UString& _fileName)
	{
		VectorUString::iterator item = std::remove(mRecentFiles.begin(), mRecentFiles.end(), _fileName);
		if (item != mRecentFiles.end())
			mRecentFiles.erase(item);

		mRecentFiles.push_back(_fileName);

		while (mRecentFiles.size() > MAX_RECENT_FILES)
			mRecentFiles.erase(mRecentFiles.begin());

		eventSettingsChanged("Main", "RecentFiles");
	}

	void SettingsManager::loadSector(MyGUI::xml::ElementPtr _sectorNode)
	{
		SettingsSector* sector = getSector(_sectorNode->getName());
		sector->deserialization(_sectorNode, MyGUI::Version());
	}

	void SettingsManager::saveSectors(MyGUI::xml::ElementPtr _rootNode)
	{
		for (VectorSettingsSector::iterator item = mSettings.begin(); item != mSettings.end(); ++item)
			(*item)->serialization(_rootNode, MyGUI::Version());
	}

	void SettingsManager::destroyAllSectors()
	{
		for (VectorSettingsSector::iterator item = mSettings.begin(); item != mSettings.end(); ++item)
			delete (*item);
		mSettings.clear();
	}

	SettingsSector* SettingsManager::getSector(const MyGUI::UString& _sectorName)
	{
		for (VectorSettingsSector::iterator item = mSettings.begin(); item != mSettings.end(); ++item)
		{
			if ((*item)->getName() == _sectorName)
				return (*item);
		}

		SettingsSector* sector = new SettingsSector();
		sector->eventSettingsChanged = MyGUI::newDelegate(this, &SettingsManager::notifySettingsChanged);

		sector->setName(_sectorName);

		mSettings.push_back(sector);
		return sector;
	}

	void SettingsManager::notifySettingsChanged(SettingsSector* _sector, const MyGUI::UString& _propertyName)
	{
		eventSettingsChanged(_sector->getName(), _propertyName);
	}

} // namespace tools
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008, 2009 Nokia Corporation.
 *
 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <QCoreApplication>
#include "halprovider.h"
#include "lowmemprovider.h"
#include "context.h"

using namespace ContextD;
using namespace ContextProvider;

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);

    Service service(QDBusConnection::SessionBus, "org.freedesktop.ContextKit.contextd");
    service.setAsDefault();
    HalProvider halProvider(service);
    LowMemProvider lowMemProvider;
    return app.exec();
}

<commit_msg>Start service.<commit_after>/*
 * Copyright (C) 2008, 2009 Nokia Corporation.
 *
 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <QCoreApplication>
#include "halprovider.h"
#include "lowmemprovider.h"
#include "context.h"

using namespace ContextD;
using namespace ContextProvider;

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);

    Service service(QDBusConnection::SessionBus, "org.freedesktop.ContextKit.contextd");
    service.setAsDefault();
    HalProvider halProvider(service);
    LowMemProvider lowMemProvider;

    service.start();
    return app.exec();
}

<|endoftext|>


<commit_before>//===- IndVarSimplify.cpp - Induction Variable Elimination ----------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// Guarantees that all loops with identifiable, linear, induction variables will
// be transformed to have a single, canonical, induction variable.  After this
// pass runs, it guarantees the the first PHI node of the header block in the
// loop is the canonical induction variable if there is one.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/iPHINode.h"
#include "llvm/iOther.h"
#include "llvm/Type.h"
#include "llvm/Constants.h"
#include "llvm/Support/CFG.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
#include "Support/STLExtras.h"
#include <algorithm>

namespace llvm {

namespace {
  Statistic<> NumRemoved ("indvars", "Number of aux indvars removed");
  Statistic<> NumInserted("indvars", "Number of canonical indvars added");
}

// InsertCast - Cast Val to Ty, setting a useful name on the cast if Val has a
// name...
//
static Instruction *InsertCast(Value *Val, const Type *Ty,
                               Instruction *InsertBefore) {
  return new CastInst(Val, Ty, Val->getName()+"-casted", InsertBefore);
}

static bool TransformLoop(LoopInfo *Loops, Loop *Loop) {
  // Transform all subloops before this loop...
  bool Changed = reduce_apply_bool(Loop->getSubLoops().begin(),
                                   Loop->getSubLoops().end(),
                              std::bind1st(std::ptr_fun(TransformLoop), Loops));
  // Get the header node for this loop.  All of the phi nodes that could be
  // induction variables must live in this basic block.
  //
  BasicBlock *Header = Loop->getHeader();

  // Loop over all of the PHI nodes in the basic block, calculating the
  // induction variables that they represent... stuffing the induction variable
  // info into a vector...
  //
  std::vector<InductionVariable> IndVars;    // Induction variables for block
  BasicBlock::iterator AfterPHIIt = Header->begin();
  for (; PHINode *PN = dyn_cast<PHINode>(AfterPHIIt); ++AfterPHIIt)
    IndVars.push_back(InductionVariable(PN, Loops));
  // AfterPHIIt now points to first non-phi instruction...

  // If there are no phi nodes in this basic block, there can't be indvars...
  if (IndVars.empty()) return Changed;

  // Loop over the induction variables, looking for a canonical induction
  // variable, and checking to make sure they are not all unknown induction
  // variables.
  //
  bool FoundIndVars = false;
  InductionVariable *Canonical = 0;
  for (unsigned i = 0; i < IndVars.size(); ++i) {
    if (IndVars[i].InductionType == InductionVariable::Canonical &&
        !isa<PointerType>(IndVars[i].Phi->getType()))
      Canonical = &IndVars[i];
    if (IndVars[i].InductionType != InductionVariable::Unknown)
      FoundIndVars = true;
  }

  // No induction variables, bail early... don't add a canonical indvar
  if (!FoundIndVars) return Changed;

  // Okay, we want to convert other induction variables to use a canonical
  // indvar.  If we don't have one, add one now...
  if (!Canonical) {
    // Create the PHI node for the new induction variable, and insert the phi
    // node at the start of the PHI nodes...
    PHINode *PN = new PHINode(Type::UIntTy, "cann-indvar", Header->begin());

    // Create the increment instruction to add one to the counter...
    Instruction *Add = BinaryOperator::create(Instruction::Add, PN,
                                              ConstantUInt::get(Type::UIntTy,1),
                                              "add1-indvar", AfterPHIIt);

    // Figure out which block is incoming and which is the backedge for the loop
    BasicBlock *Incoming, *BackEdgeBlock;
    pred_iterator PI = pred_begin(Header);
    assert(PI != pred_end(Header) && "Loop headers should have 2 preds!");
    if (Loop->contains(*PI)) {  // First pred is back edge...
      BackEdgeBlock = *PI++;
      Incoming      = *PI++;
    } else {
      Incoming      = *PI++;
      BackEdgeBlock = *PI++;
    }
    assert(PI == pred_end(Header) && "Loop headers should have 2 preds!");

    // Add incoming values for the PHI node...
    PN->addIncoming(Constant::getNullValue(Type::UIntTy), Incoming);
    PN->addIncoming(Add, BackEdgeBlock);

    // Analyze the new induction variable...
    IndVars.push_back(InductionVariable(PN, Loops));
    assert(IndVars.back().InductionType == InductionVariable::Canonical &&
           "Just inserted canonical indvar that is not canonical!");
    Canonical = &IndVars.back();
    ++NumInserted;
    Changed = true;
  } else {
    // If we have a canonical induction variable, make sure that it is the first
    // one in the basic block.
    if (&Header->front() != Canonical->Phi)
      Header->getInstList().splice(Header->begin(), Header->getInstList(),
                                   Canonical->Phi);
  }

  DEBUG(std::cerr << "Induction variables:\n");

  // Get the current loop iteration count, which is always the value of the
  // canonical phi node...
  //
  PHINode *IterCount = Canonical->Phi;

  // Loop through and replace all of the auxiliary induction variables with
  // references to the canonical induction variable...
  //
  for (unsigned i = 0; i < IndVars.size(); ++i) {
    InductionVariable *IV = &IndVars[i];

    DEBUG(IV->print(std::cerr));

    // Don't do math with pointers...
    const Type *IVTy = IV->Phi->getType();
    if (isa<PointerType>(IVTy)) IVTy = Type::ULongTy;

    // Don't modify the canonical indvar or unrecognized indvars...
    if (IV != Canonical && IV->InductionType != InductionVariable::Unknown) {
      Instruction *Val = IterCount;
      if (!isa<ConstantInt>(IV->Step) ||   // If the step != 1
          !cast<ConstantInt>(IV->Step)->equalsInt(1)) {

        // If the types are not compatible, insert a cast now...
        if (Val->getType() != IVTy)
          Val = InsertCast(Val, IVTy, AfterPHIIt);
        if (IV->Step->getType() != IVTy)
          IV->Step = InsertCast(IV->Step, IVTy, AfterPHIIt);

        Val = BinaryOperator::create(Instruction::Mul, Val, IV->Step,
                                     IV->Phi->getName()+"-scale", AfterPHIIt);
      }

      // If the start != 0
      if (IV->Start != Constant::getNullValue(IV->Start->getType())) {
        // If the types are not compatible, insert a cast now...
        if (Val->getType() != IVTy)
          Val = InsertCast(Val, IVTy, AfterPHIIt);
        if (IV->Start->getType() != IVTy)
          IV->Start = InsertCast(IV->Start, IVTy, AfterPHIIt);

        // Insert the instruction after the phi nodes...
        Val = BinaryOperator::create(Instruction::Add, Val, IV->Start,
                                     IV->Phi->getName()+"-offset", AfterPHIIt);
      }

      // If the PHI node has a different type than val is, insert a cast now...
      if (Val->getType() != IV->Phi->getType())
        Val = InsertCast(Val, IV->Phi->getType(), AfterPHIIt);

      // Replace all uses of the old PHI node with the new computed value...
      IV->Phi->replaceAllUsesWith(Val);

      // Move the PHI name to it's new equivalent value...
      std::string OldName = IV->Phi->getName();
      IV->Phi->setName("");
      Val->setName(OldName);

      // Delete the old, now unused, phi node...
      Header->getInstList().erase(IV->Phi);

      // If the PHI is the last user of any instructions for computing PHI nodes
      // that are irrelevant now, delete those instructions.
      while (!PHIOps.empty()) {
        Instruction *MaybeDead = dyn_cast<Instruction>(PHIOps.back());
        PHIOps.pop_back();

        if (MaybeDead && isInstructionTriviallyDead(MaybeDead)) {
          PHIOps.insert(PHIOps.end(), MaybeDead->op_begin(),
                        MaybeDead->op_end());
          MaybeDead->getParent()->getInstList().erase(MaybeDead);

          // Erase any duplicates entries in the PHIOps list.
          std::vector<Value*>::iterator It =
            std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
          while (It != PHIOps.end()) {
            PHIOps.erase(It);
            It = std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
          }

          // Erasing the instruction could invalidate the AfterPHI iterator!
          AfterPHIIt = Header->begin();
        }
      }

      Changed = true;
      ++NumRemoved;
    }
  }

  return Changed;
}

namespace {
  struct InductionVariableSimplify : public FunctionPass {
    virtual bool runOnFunction(Function &) {
      LoopInfo &LI = getAnalysis<LoopInfo>();

      // Induction Variables live in the header nodes of loops
      return reduce_apply_bool(LI.getTopLevelLoops().begin(),
                               LI.getTopLevelLoops().end(),
                               std::bind1st(std::ptr_fun(TransformLoop), &LI));
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.setPreservesCFG();
    }
  };
  RegisterOpt<InductionVariableSimplify> X("indvars",
                                           "Canonicalize Induction Variables");
}

Pass *createIndVarSimplifyPass() {
  return new InductionVariableSimplify();
}

} // End llvm namespace
<commit_msg>Reverted back to previous revision - this was previously merged according to the CVS log messages.<commit_after>//===- IndVarSimplify.cpp - Induction Variable Elimination ----------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// Guarantees that all loops with identifiable, linear, induction variables will
// be transformed to have a single, canonical, induction variable.  After this
// pass runs, it guarantees the the first PHI node of the header block in the
// loop is the canonical induction variable if there is one.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/iPHINode.h"
#include "llvm/iOther.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/CFG.h"
#include "llvm/Transforms/Utils/Local.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
#include "Support/STLExtras.h"
#include <algorithm>
using namespace llvm;

namespace {
  Statistic<> NumRemoved ("indvars", "Number of aux indvars removed");
  Statistic<> NumInserted("indvars", "Number of canonical indvars added");
}

// InsertCast - Cast Val to Ty, setting a useful name on the cast if Val has a
// name...
//
static Instruction *InsertCast(Value *Val, const Type *Ty,
                               Instruction *InsertBefore) {
  return new CastInst(Val, Ty, Val->getName()+"-casted", InsertBefore);
}

static bool TransformLoop(LoopInfo *Loops, Loop *Loop) {
  // Transform all subloops before this loop...
  bool Changed = reduce_apply_bool(Loop->getSubLoops().begin(),
                                   Loop->getSubLoops().end(),
                              std::bind1st(std::ptr_fun(TransformLoop), Loops));
  // Get the header node for this loop.  All of the phi nodes that could be
  // induction variables must live in this basic block.
  //
  BasicBlock *Header = Loop->getHeader();

  // Loop over all of the PHI nodes in the basic block, calculating the
  // induction variables that they represent... stuffing the induction variable
  // info into a vector...
  //
  std::vector<InductionVariable> IndVars;    // Induction variables for block
  BasicBlock::iterator AfterPHIIt = Header->begin();
  for (; PHINode *PN = dyn_cast<PHINode>(AfterPHIIt); ++AfterPHIIt)
    IndVars.push_back(InductionVariable(PN, Loops));
  // AfterPHIIt now points to first non-phi instruction...

  // If there are no phi nodes in this basic block, there can't be indvars...
  if (IndVars.empty()) return Changed;

  // Loop over the induction variables, looking for a canonical induction
  // variable, and checking to make sure they are not all unknown induction
  // variables.
  //
  bool FoundIndVars = false;
  InductionVariable *Canonical = 0;
  for (unsigned i = 0; i < IndVars.size(); ++i) {
    if (IndVars[i].InductionType == InductionVariable::Canonical &&
        !isa<PointerType>(IndVars[i].Phi->getType()))
      Canonical = &IndVars[i];
    if (IndVars[i].InductionType != InductionVariable::Unknown)
      FoundIndVars = true;
  }

  // No induction variables, bail early... don't add a canonical indvar
  if (!FoundIndVars) return Changed;

  // Okay, we want to convert other induction variables to use a canonical
  // indvar.  If we don't have one, add one now...
  if (!Canonical) {
    // Create the PHI node for the new induction variable, and insert the phi
    // node at the start of the PHI nodes...
    PHINode *PN = new PHINode(Type::UIntTy, "cann-indvar", Header->begin());

    // Create the increment instruction to add one to the counter...
    Instruction *Add = BinaryOperator::create(Instruction::Add, PN,
                                              ConstantUInt::get(Type::UIntTy,1),
                                              "add1-indvar", AfterPHIIt);

    // Figure out which block is incoming and which is the backedge for the loop
    BasicBlock *Incoming, *BackEdgeBlock;
    pred_iterator PI = pred_begin(Header);
    assert(PI != pred_end(Header) && "Loop headers should have 2 preds!");
    if (Loop->contains(*PI)) {  // First pred is back edge...
      BackEdgeBlock = *PI++;
      Incoming      = *PI++;
    } else {
      Incoming      = *PI++;
      BackEdgeBlock = *PI++;
    }
    assert(PI == pred_end(Header) && "Loop headers should have 2 preds!");

    // Add incoming values for the PHI node...
    PN->addIncoming(Constant::getNullValue(Type::UIntTy), Incoming);
    PN->addIncoming(Add, BackEdgeBlock);

    // Analyze the new induction variable...
    IndVars.push_back(InductionVariable(PN, Loops));
    assert(IndVars.back().InductionType == InductionVariable::Canonical &&
           "Just inserted canonical indvar that is not canonical!");
    Canonical = &IndVars.back();
    ++NumInserted;
    Changed = true;
  } else {
    // If we have a canonical induction variable, make sure that it is the first
    // one in the basic block.
    if (&Header->front() != Canonical->Phi)
      Header->getInstList().splice(Header->begin(), Header->getInstList(),
                                   Canonical->Phi);
  }

  DEBUG(std::cerr << "Induction variables:\n");

  // Get the current loop iteration count, which is always the value of the
  // canonical phi node...
  //
  PHINode *IterCount = Canonical->Phi;

  // Loop through and replace all of the auxiliary induction variables with
  // references to the canonical induction variable...
  //
  for (unsigned i = 0; i < IndVars.size(); ++i) {
    InductionVariable *IV = &IndVars[i];

    DEBUG(IV->print(std::cerr));

    while (isa<PHINode>(AfterPHIIt)) ++AfterPHIIt;

    // Don't do math with pointers...
    const Type *IVTy = IV->Phi->getType();
    if (isa<PointerType>(IVTy)) IVTy = Type::ULongTy;

    // Don't modify the canonical indvar or unrecognized indvars...
    if (IV != Canonical && IV->InductionType != InductionVariable::Unknown) {
      Instruction *Val = IterCount;
      if (!isa<ConstantInt>(IV->Step) ||   // If the step != 1
          !cast<ConstantInt>(IV->Step)->equalsInt(1)) {

        // If the types are not compatible, insert a cast now...
        if (Val->getType() != IVTy)
          Val = InsertCast(Val, IVTy, AfterPHIIt);
        if (IV->Step->getType() != IVTy)
          IV->Step = InsertCast(IV->Step, IVTy, AfterPHIIt);

        Val = BinaryOperator::create(Instruction::Mul, Val, IV->Step,
                                     IV->Phi->getName()+"-scale", AfterPHIIt);
      }

      // If the start != 0
      if (IV->Start != Constant::getNullValue(IV->Start->getType())) {
        // If the types are not compatible, insert a cast now...
        if (Val->getType() != IVTy)
          Val = InsertCast(Val, IVTy, AfterPHIIt);
        if (IV->Start->getType() != IVTy)
          IV->Start = InsertCast(IV->Start, IVTy, AfterPHIIt);

        // Insert the instruction after the phi nodes...
        Val = BinaryOperator::create(Instruction::Add, Val, IV->Start,
                                     IV->Phi->getName()+"-offset", AfterPHIIt);
      }

      // If the PHI node has a different type than val is, insert a cast now...
      if (Val->getType() != IV->Phi->getType())
        Val = InsertCast(Val, IV->Phi->getType(), AfterPHIIt);

      // Replace all uses of the old PHI node with the new computed value...
      IV->Phi->replaceAllUsesWith(Val);

      // Move the PHI name to it's new equivalent value...
      std::string OldName = IV->Phi->getName();
      IV->Phi->setName("");
      Val->setName(OldName);

      // Get the incoming values used by the PHI node
      std::vector<Value*> PHIOps;
      PHIOps.reserve(IV->Phi->getNumIncomingValues());
      for (unsigned i = 0, e = IV->Phi->getNumIncomingValues(); i != e; ++i)
        PHIOps.push_back(IV->Phi->getIncomingValue(i));

      // Delete the old, now unused, phi node...
      Header->getInstList().erase(IV->Phi);

      // If the PHI is the last user of any instructions for computing PHI nodes
      // that are irrelevant now, delete those instructions.
      while (!PHIOps.empty()) {
        Instruction *MaybeDead = dyn_cast<Instruction>(PHIOps.back());
        PHIOps.pop_back();

        if (MaybeDead && isInstructionTriviallyDead(MaybeDead)) {
          PHIOps.insert(PHIOps.end(), MaybeDead->op_begin(),
                        MaybeDead->op_end());
          MaybeDead->getParent()->getInstList().erase(MaybeDead);

          // Erase any duplicates entries in the PHIOps list.
          std::vector<Value*>::iterator It =
            std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
          while (It != PHIOps.end()) {
            PHIOps.erase(It);
            It = std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
          }

          // Erasing the instruction could invalidate the AfterPHI iterator!
          AfterPHIIt = Header->begin();
        }
      }

      Changed = true;
      ++NumRemoved;
    }
  }

  return Changed;
}

namespace {
  struct InductionVariableSimplify : public FunctionPass {
    virtual bool runOnFunction(Function &) {
      LoopInfo &LI = getAnalysis<LoopInfo>();

      // Induction Variables live in the header nodes of loops
      return reduce_apply_bool(LI.getTopLevelLoops().begin(),
                               LI.getTopLevelLoops().end(),
                               std::bind1st(std::ptr_fun(TransformLoop), &LI));
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.setPreservesCFG();
    }
  };
  RegisterOpt<InductionVariableSimplify> X("indvars",
                                           "Canonicalize Induction Variables");
}

Pass *llvm::createIndVarSimplifyPass() {
  return new InductionVariableSimplify();
}

<|endoftext|>


<commit_before>//===-- LoopUnroll.cpp - Loop unroller pass -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass implements a simple loop unroller.  It works best when loops have
// been canonicalized by the -indvars pass, allowing it to determine the trip
// counts of loops easily.
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "loop-unroll"
#include "llvm/IntrinsicInst.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/CodeMetrics.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/UnrollLoop.h"
#include <climits>

using namespace llvm;

static cl::opt<unsigned>
UnrollThreshold("unroll-threshold", cl::init(150), cl::Hidden,
  cl::desc("The cut-off point for automatic loop unrolling"));

static cl::opt<unsigned>
UnrollCount("unroll-count", cl::init(0), cl::Hidden,
  cl::desc("Use this unroll count for all loops, for testing purposes"));

static cl::opt<bool>
UnrollAllowPartial("unroll-allow-partial", cl::init(false), cl::Hidden,
  cl::desc("Allows loops to be partially unrolled until "
           "-unroll-threshold loop size is reached."));

namespace {
  class LoopUnroll : public LoopPass {
  public:
    static char ID; // Pass ID, replacement for typeid
    LoopUnroll(int T = -1, int C = -1,  int P = -1) : LoopPass(ID) {
      CurrentThreshold = (T == -1) ? UnrollThreshold : T;
      CurrentCount = (C == -1) ? UnrollCount : C;
      CurrentAllowPartial = (P == -1) ? UnrollAllowPartial : (bool)P;

      UserThreshold = (T != -1) || (UnrollThreshold.getNumOccurrences() > 0);

      initializeLoopUnrollPass(*PassRegistry::getPassRegistry());
    }

    /// A magic value for use with the Threshold parameter to indicate
    /// that the loop unroll should be performed regardless of how much
    /// code expansion would result.
    static const unsigned NoThreshold = UINT_MAX;

    // Threshold to use when optsize is specified (and there is no
    // explicit -unroll-threshold).
    static const unsigned OptSizeUnrollThreshold = 50;

    unsigned CurrentCount;
    unsigned CurrentThreshold;
    bool     CurrentAllowPartial;
    bool     UserThreshold;        // CurrentThreshold is user-specified.

    bool runOnLoop(Loop *L, LPPassManager &LPM);

    /// This transformation requires natural loop information & requires that
    /// loop preheaders be inserted into the CFG...
    ///
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<LoopInfo>();
      AU.addPreserved<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.addPreservedID(LoopSimplifyID);
      AU.addRequiredID(LCSSAID);
      AU.addPreservedID(LCSSAID);
      AU.addPreserved<ScalarEvolution>();
      // FIXME: Loop unroll requires LCSSA. And LCSSA requires dom info.
      // If loop unroll does not preserve dom info then LCSSA pass on next
      // loop will receive invalid dom info.
      // For now, recreate dom info, if loop is unrolled.
      AU.addPreserved<DominatorTree>();
    }
  };
}

char LoopUnroll::ID = 0;
INITIALIZE_PASS_BEGIN(LoopUnroll, "loop-unroll", "Unroll loops", false, false)
INITIALIZE_PASS_DEPENDENCY(LoopInfo)
INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
INITIALIZE_PASS_DEPENDENCY(LCSSA)
INITIALIZE_PASS_END(LoopUnroll, "loop-unroll", "Unroll loops", false, false)

Pass *llvm::createLoopUnrollPass(int Threshold, int Count, int AllowPartial) {
  return new LoopUnroll();
}

/// ApproximateLoopSize - Approximate the size of the loop.
static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls) {
  CodeMetrics Metrics;
  for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
       I != E; ++I)
    Metrics.analyzeBasicBlock(*I);
  NumCalls = Metrics.NumInlineCandidates;

  unsigned LoopSize = Metrics.NumInsts;

  // Don't allow an estimate of size zero.  This would allows unrolling of loops
  // with huge iteration counts, which is a compile time problem even if it's
  // not a problem for code quality.
  if (LoopSize == 0) LoopSize = 1;

  return LoopSize;
}

bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
  LoopInfo *LI = &getAnalysis<LoopInfo>();

  BasicBlock *Header = L->getHeader();
  DEBUG(dbgs() << "Loop Unroll: F[" << Header->getParent()->getName()
        << "] Loop %" << Header->getName() << "\n");
  (void)Header;

  // Determine the current unrolling threshold.  While this is normally set
  // from UnrollThreshold, it is overridden to a smaller value if the current
  // function is marked as optimize-for-size, and the unroll threshold was
  // not user specified.
  unsigned Threshold = CurrentThreshold;
  if (!UserThreshold &&
      Header->getParent()->hasFnAttr(Attribute::OptimizeForSize))
    Threshold = OptSizeUnrollThreshold;

  // Find trip count
  unsigned TripCount = L->getSmallConstantTripCount();
  unsigned Count = CurrentCount;

  // Automatically select an unroll count.
  if (Count == 0) {
    // Conservative heuristic: if we know the trip count, see if we can
    // completely unroll (subject to the threshold, checked below); otherwise
    // try to find greatest modulo of the trip count which is still under
    // threshold value.
    if (TripCount == 0)
      return false;
    Count = TripCount;
  }

  // Enforce the threshold.
  if (Threshold != NoThreshold) {
    unsigned NumInlineCandidates;
    unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates);
    DEBUG(dbgs() << "  Loop Size = " << LoopSize << "\n");
    if (NumInlineCandidates != 0) {
      DEBUG(dbgs() << "  Not unrolling loop with inlinable calls.\n");
      return false;
    }
    uint64_t Size = (uint64_t)LoopSize*Count;
    if (TripCount != 1 && Size > Threshold) {
      DEBUG(dbgs() << "  Too large to fully unroll with count: " << Count
            << " because size: " << Size << ">" << Threshold << "\n");
      if (!CurrentAllowPartial) {
        DEBUG(dbgs() << "  will not try to unroll partially because "
              << "-unroll-allow-partial not given\n");
        return false;
      }
      // Reduce unroll count to be modulo of TripCount for partial unrolling
      Count = Threshold / LoopSize;
      while (Count != 0 && TripCount%Count != 0) {
        Count--;
      }
      if (Count < 2) {
        DEBUG(dbgs() << "  could not unroll partially\n");
        return false;
      }
      DEBUG(dbgs() << "  partially unrolling with count: " << Count << "\n");
    }
  }

  // Unroll the loop.
  Function *F = L->getHeader()->getParent();
  if (!UnrollLoop(L, Count, LI, &LPM))
    return false;

  // FIXME: Reconstruct dom info, because it is not preserved properly.
  if (DominatorTree *DT = getAnalysisIfAvailable<DominatorTree>())
    DT->runOnFunction(*F);
  return true;
}
<commit_msg>Fixed the revision 129449.<commit_after>//===-- LoopUnroll.cpp - Loop unroller pass -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass implements a simple loop unroller.  It works best when loops have
// been canonicalized by the -indvars pass, allowing it to determine the trip
// counts of loops easily.
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "loop-unroll"
#include "llvm/IntrinsicInst.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/CodeMetrics.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/UnrollLoop.h"
#include <climits>

using namespace llvm;

static cl::opt<unsigned>
UnrollThreshold("unroll-threshold", cl::init(150), cl::Hidden,
  cl::desc("The cut-off point for automatic loop unrolling"));

static cl::opt<unsigned>
UnrollCount("unroll-count", cl::init(0), cl::Hidden,
  cl::desc("Use this unroll count for all loops, for testing purposes"));

static cl::opt<bool>
UnrollAllowPartial("unroll-allow-partial", cl::init(false), cl::Hidden,
  cl::desc("Allows loops to be partially unrolled until "
           "-unroll-threshold loop size is reached."));

namespace {
  class LoopUnroll : public LoopPass {
  public:
    static char ID; // Pass ID, replacement for typeid
    LoopUnroll(int T = -1, int C = -1,  int P = -1) : LoopPass(ID) {
      CurrentThreshold = (T == -1) ? UnrollThreshold : T;
      CurrentCount = (C == -1) ? UnrollCount : C;
      CurrentAllowPartial = (P == -1) ? UnrollAllowPartial : (bool)P;

      UserThreshold = (T != -1) || (UnrollThreshold.getNumOccurrences() > 0);

      initializeLoopUnrollPass(*PassRegistry::getPassRegistry());
    }

    /// A magic value for use with the Threshold parameter to indicate
    /// that the loop unroll should be performed regardless of how much
    /// code expansion would result.
    static const unsigned NoThreshold = UINT_MAX;

    // Threshold to use when optsize is specified (and there is no
    // explicit -unroll-threshold).
    static const unsigned OptSizeUnrollThreshold = 50;

    unsigned CurrentCount;
    unsigned CurrentThreshold;
    bool     CurrentAllowPartial;
    bool     UserThreshold;        // CurrentThreshold is user-specified.

    bool runOnLoop(Loop *L, LPPassManager &LPM);

    /// This transformation requires natural loop information & requires that
    /// loop preheaders be inserted into the CFG...
    ///
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<LoopInfo>();
      AU.addPreserved<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.addPreservedID(LoopSimplifyID);
      AU.addRequiredID(LCSSAID);
      AU.addPreservedID(LCSSAID);
      AU.addPreserved<ScalarEvolution>();
      // FIXME: Loop unroll requires LCSSA. And LCSSA requires dom info.
      // If loop unroll does not preserve dom info then LCSSA pass on next
      // loop will receive invalid dom info.
      // For now, recreate dom info, if loop is unrolled.
      AU.addPreserved<DominatorTree>();
    }
  };
}

char LoopUnroll::ID = 0;
INITIALIZE_PASS_BEGIN(LoopUnroll, "loop-unroll", "Unroll loops", false, false)
INITIALIZE_PASS_DEPENDENCY(LoopInfo)
INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
INITIALIZE_PASS_DEPENDENCY(LCSSA)
INITIALIZE_PASS_END(LoopUnroll, "loop-unroll", "Unroll loops", false, false)

Pass *llvm::createLoopUnrollPass(int Threshold, int Count, int AllowPartial) {
  return new LoopUnroll(Threshold, Count, AllowPartial);
}

/// ApproximateLoopSize - Approximate the size of the loop.
static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls) {
  CodeMetrics Metrics;
  for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
       I != E; ++I)
    Metrics.analyzeBasicBlock(*I);
  NumCalls = Metrics.NumInlineCandidates;

  unsigned LoopSize = Metrics.NumInsts;

  // Don't allow an estimate of size zero.  This would allows unrolling of loops
  // with huge iteration counts, which is a compile time problem even if it's
  // not a problem for code quality.
  if (LoopSize == 0) LoopSize = 1;

  return LoopSize;
}

bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
  LoopInfo *LI = &getAnalysis<LoopInfo>();

  BasicBlock *Header = L->getHeader();
  DEBUG(dbgs() << "Loop Unroll: F[" << Header->getParent()->getName()
        << "] Loop %" << Header->getName() << "\n");
  (void)Header;

  // Determine the current unrolling threshold.  While this is normally set
  // from UnrollThreshold, it is overridden to a smaller value if the current
  // function is marked as optimize-for-size, and the unroll threshold was
  // not user specified.
  unsigned Threshold = CurrentThreshold;
  if (!UserThreshold &&
      Header->getParent()->hasFnAttr(Attribute::OptimizeForSize))
    Threshold = OptSizeUnrollThreshold;

  // Find trip count
  unsigned TripCount = L->getSmallConstantTripCount();
  unsigned Count = CurrentCount;

  // Automatically select an unroll count.
  if (Count == 0) {
    // Conservative heuristic: if we know the trip count, see if we can
    // completely unroll (subject to the threshold, checked below); otherwise
    // try to find greatest modulo of the trip count which is still under
    // threshold value.
    if (TripCount == 0)
      return false;
    Count = TripCount;
  }

  // Enforce the threshold.
  if (Threshold != NoThreshold) {
    unsigned NumInlineCandidates;
    unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates);
    DEBUG(dbgs() << "  Loop Size = " << LoopSize << "\n");
    if (NumInlineCandidates != 0) {
      DEBUG(dbgs() << "  Not unrolling loop with inlinable calls.\n");
      return false;
    }
    uint64_t Size = (uint64_t)LoopSize*Count;
    if (TripCount != 1 && Size > Threshold) {
      DEBUG(dbgs() << "  Too large to fully unroll with count: " << Count
            << " because size: " << Size << ">" << Threshold << "\n");
      if (!CurrentAllowPartial) {
        DEBUG(dbgs() << "  will not try to unroll partially because "
              << "-unroll-allow-partial not given\n");
        return false;
      }
      // Reduce unroll count to be modulo of TripCount for partial unrolling
      Count = Threshold / LoopSize;
      while (Count != 0 && TripCount%Count != 0) {
        Count--;
      }
      if (Count < 2) {
        DEBUG(dbgs() << "  could not unroll partially\n");
        return false;
      }
      DEBUG(dbgs() << "  partially unrolling with count: " << Count << "\n");
    }
  }

  // Unroll the loop.
  Function *F = L->getHeader()->getParent();
  if (!UnrollLoop(L, Count, LI, &LPM))
    return false;

  // FIXME: Reconstruct dom info, because it is not preserved properly.
  if (DominatorTree *DT = getAnalysisIfAvailable<DominatorTree>())
    DT->runOnFunction(*F);
  return true;
}
<|endoftext|>