/*
 * Copyright (C) 2016 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "B3SSACalculator.h"

#if ENABLE(B3_JIT)

#include <wtf/CommaPrinter.h>

namespace JSC { namespace B3 {

void SSACalculator::Variable::dump(PrintStream& out) const
{
    out.print("var", m_index);
}

void SSACalculator::Variable::dumpVerbose(PrintStream& out) const
{
    dump(out);
    if (!m_blocksWithDefs.isEmpty()) {
        out.print("(defs: ");
        CommaPrinter comma;
        for (BasicBlock* block : m_blocksWithDefs)
            out.print(comma, *block);
        out.print(")");
    }
}

void SSACalculator::Def::dump(PrintStream& out) const
{
    out.print("def(", *m_variable, ", ", *m_block, ", ", pointerDump(m_value), ")");
}

SSACalculator::SSACalculator(Procedure& proc)
    : m_data(proc.size())
    , m_proc(proc)
{
}

SSACalculator::~SSACalculator()
{
}

void SSACalculator::reset()
{
    m_variables.clear();
    m_defs.clear();
    m_phis.clear();
    for (unsigned blockIndex = m_data.size(); blockIndex--;) {
        m_data[blockIndex].m_defs.clear();
        m_data[blockIndex].m_phis.clear();
    }
}

SSACalculator::Variable* SSACalculator::newVariable()
{
    return &m_variables.alloc(Variable(m_variables.size()));
}

SSACalculator::Def* SSACalculator::newDef(Variable* variable, BasicBlock* block, Value* value)
{
    Def* def = m_defs.add(Def(variable, block, value));
    auto result = m_data[block].m_defs.add(variable, def);
    if (result.isNewEntry)
        variable->m_blocksWithDefs.append(block);
    else
        result.iterator->value = def;
    return def;
}

SSACalculator::Def* SSACalculator::nonLocalReachingDef(BasicBlock* block, Variable* variable)
{
    return reachingDefAtTail(m_dominators->idom(block), variable);
}

SSACalculator::Def* SSACalculator::reachingDefAtTail(BasicBlock* startingBlock, Variable* variable)
{
    for (BasicBlock* block = startingBlock; block; block = m_dominators->idom(block)) {
        if (Def* def = m_data[block].m_defs.get(variable)) {
            for (BasicBlock* otherBlock = startingBlock; otherBlock != block; otherBlock = m_dominators->idom(otherBlock))
                m_data[block].m_defs.add(variable, def);
            return def;
        }
    }
    return nullptr;
}

void SSACalculator::dump(PrintStream& out) const
{
    out.print("<Variables: [");
    CommaPrinter comma;
    for (unsigned i = 0; i < m_variables.size(); ++i) {
        out.print(comma);
        m_variables[i].dumpVerbose(out);
    }
    out.print("], Defs: [");
    comma = CommaPrinter();
    for (Def* def : const_cast<SSACalculator*>(this)->m_defs)
        out.print(comma, *def);
    out.print("], Phis: [");
    comma = CommaPrinter();
    for (Def* def : const_cast<SSACalculator*>(this)->m_phis)
        out.print(comma, *def);
    out.print("], Block data: [");
    comma = CommaPrinter();
    for (unsigned blockIndex = 0; blockIndex < m_proc.size(); ++blockIndex) {
        BasicBlock* block = m_proc[blockIndex];
        if (!block)
            continue;
        
        out.print(comma, *block, "=>(");
        out.print("Defs: {");
        CommaPrinter innerComma;
        for (auto entry : m_data[block].m_defs)
            out.print(innerComma, *entry.key, "->", *entry.value);
        out.print("}, Phis: {");
        innerComma = CommaPrinter();
        for (Def* def : m_data[block].m_phis)
            out.print(innerComma, *def);
        out.print("})");
    }
    out.print("]>");
}

} } // namespace JSC::B3

#endif // ENABLE(B3_JIT)

