ClangFixItOperationsExtractor::ClangFixItOperationsExtractor(
        const QVector<DiagnosticContainer> &diagnosticContainers)
    : diagnosticContainers(diagnosticContainers)
{
}

/****************************************************************************
**
**
** This file is part of Qt Creator.
**
**
****************************************************************************/

#include "clangfixitoperationsextractor.h"

#include "clangfixitoperation.h"
#include "clangutils.h"

#include <utils/algorithm.h>

#include <QDebug>

using ClangBackEnd::DiagnosticContainer;

namespace ClangCodeModel {
namespace Internal {

namespace {

void capitalizeText(QString &text)
{
    text[0] = text[0].toUpper();
}

QString tweakedDiagnosticText(const QString &diagnosticText)
{
    // "note: use '==' to turn this assignment into an equality comparison"
    // "error: expected ';' at end of declaration"

    QString tweakedText = diagnosticText;

    if (!tweakedText.isEmpty()) {
        tweakedText = diagnosticCategoryPrefixRemoved(tweakedText);
        capitalizeText(tweakedText);
    }

    return tweakedText;
}

bool hasFixItAt(const QVector<ClangBackEnd::FixItContainer> &fixits,
                const Utf8String &filePath,
                int line)
{
    const auto isFixitForLocation = [filePath, line] (const ClangBackEnd::FixItContainer &fixit) {
        const ClangBackEnd::SourceLocationContainer &location = fixit.range.start;
        return location.filePath == filePath && location.line == line;
    };

    return Utils::anyOf(fixits, isFixitForLocation);
}

} // anonymous namespace

TextEditor::QuickFixOperations
ClangFixItOperationsExtractor::extract(const QString &filePath, int line)
{
    foreach (const DiagnosticContainer &diagnosticContainer, diagnosticContainers)
        extractFromDiagnostic(diagnosticContainer, filePath, line);

    return operations;
}

void ClangFixItOperationsExtractor::appendFixitOperation(
        const QString &diagnosticText,
        const QVector<ClangBackEnd::FixItContainer> &fixits)
{
    if (!fixits.isEmpty()) {
        const QString diagnosticTextTweaked = tweakedDiagnosticText(diagnosticText);
        TextEditor::QuickFixOperation::Ptr operation(
                    new ClangFixItOperation(diagnosticTextTweaked, fixits));
        operations.append(operation);
    }
}

void ClangFixItOperationsExtractor::extractFromDiagnostic(
        const DiagnosticContainer &diagnosticContainer,
        const QString &filePath,
        int line)
{
    const QVector<ClangBackEnd::FixItContainer> &fixIts = diagnosticContainer.fixIts;
    if (hasFixItAt(fixIts, filePath, line)) {
        appendFixitOperation(diagnosticContainer.text.toString(), fixIts);

        for (const auto &child : diagnosticContainer.children)
            extractFromDiagnostic(child, filePath, line);
    }
}

} // namespace Internal
} // namespace ClangCodeModel


int main() {

  // we need the SysTick timer

  MillisecondTimer::initialise();

  TimerPwmBreakTest test;
  test.run();

  // not reached
  return 0;
}

/*
 * This file is a part of the open source stm32plus library.
 * Please see website for licensing terms.
 */

#include "config/stm32plus.h"
#include "config/timer.h"
#include "config/timing.h"

using namespace stm32plus;

/**
 * Timer demonstration including the break input feature: Use timer 1 to output a 1MHz PWM wave on
 * channel 1 (PA8). The demo will repeatedly increment the duty cycle from 0 to 100% and back down
 * to 0 over 800ms. When the break input is triggered (low to high) the PWM output will stop and
 * be reset to the programmed idle state (low).
 *
 * Connect up PA8 to a LED pin on your development board to see the output. Connect up the break input
 * (PB12) to GND when you launch the demo.
 *
 * To trigger the break input remove the connection from PB12 to GND. This alone will probably be enough
 * to trigger the break. If not then connect it to the board's VCC voltage (probably 3V or 3.3V). The
 * break interrupt will repeatedly trigger until you reconnect PB12 to ground.
 *
 * It's up to you to recover from the break in the interrupt handler before re-enabling the outputs. If
 * you want the outputs to be automatically re-enabled at the next reload event then call enableAutomaticOutput()
 * during the timer setup.
 *
 * Compatible MCU:
 *   STM32F0
 *   STM32F1
 *   STM32F4
 *
 * Tested on devices:
 *   STM32F407VGT6
 *   STM32F051R8T6
 *   STM32F103VET6
 */

class TimerPwmBreakTest {

  public:

    void run() {

      /*
       * Initialise timer1 running from the internal APB2 clock with channel-1 and GPIO output features.
       * The GPIO output feature is itself configured with a channel-1 output feature.
       */

      Timer1<
        Timer1InternalClockFeature,       // the timer clock source is APB1
        UnlockedTimerBreakFeature,        // we want the break functionality
        TimerChannel1Feature<             // we're going to use channel 1 with the OC idle state = low
          TimerChannelOCPWM1ModeFeature,
          TimerChannelOCHighPolarityFeature,
          TimerChannelOCLowIdleFeature
        >,
        Timer1GpioFeature<                // we want to output something to GPIO
          TIMER_REMAP_NONE,               // the GPIO output will not be remapped
          TIM1_CH1_OUT,                   // we will output channel 1 to GPIO
          TIM1_BKIN                       // break input on PB12
        >,
        Timer1InterruptFeature
      > timer;

      /*
       * Set ourselves up as a subscriber for interrupts raised by the timer class.
       */

      timer.TimerInterruptEventSender.insertSubscriber(
          TimerInterruptEventSourceSlot::bind(this,&TimerPwmBreakTest::onInterrupt)
        );

      /*
       * Set an up-timer up to tick at 10MHz with an auto-reload value of 1999
       * The timer will count from 0 to 1999 inclusive then reset back to 0.
       */

      timer.setTimeBaseByFrequency(10000000,1999);

      /*
       * Clear and enable interrupts
       */

      timer.clearPendingInterruptsFlag(TIM_IT_Break);
      timer.enableInterrupts(TIM_IT_Break);

      /*
       * Default duty cycle of zero
       */

      timer.setDutyCycle(0);

      /*
       * Master output enable (timers with the break feature have this disabled after reset)
       */

      timer.enableMainOutput();

      /*
       * Enable the break feature
       */

      timer.setBreakPolarity(UnlockedTimerBreakFeature::BREAK_POLARITY_HIGH);
      timer.enableBreak();

      /*
       * Enable the timer. The PWM output is on PA8.
       */

      timer.enablePeripheral();

      /*
       * It's all running automatically now, use the main CPU to vary the duty cycle up
       * to 100% and back down again
       */

      for(;;) {

        // fade up to 100% in 4ms steps

        for(int8_t i=0;i<=100;i++) {
          timer.setDutyCycle(i);
          MillisecondTimer::delay(4);
        }

        // fade down to 0% in 4ms steps

        for(int8_t i=100;i>=0;i--) {
          timer.setDutyCycle(i);
          MillisecondTimer::delay(4);
        }
      }
    }

    /*
     * Subscriber callback function
     */

    void onInterrupt(TimerEventType tet,uint8_t /* timerNumber */) {

      if(tet==TimerEventType::EVENT_BREAK) {
        // do something to handle the break event
      }
    }
};

/*
 * Main entry point
 */


void Utf8Encoder::resize(size_t size)
{
    if (mOutput.size() <= size)
        // Add some extra padding to reduce the chance of having to resize
        // again later.
        mOutput.resize(3*size);

    // And make sure the string is zero terminated
    mOutput[size] = 0;
}

#include "to_utf8.hpp"

#include <vector>
#include <cassert>
#include <stdexcept>

#include <components/debug/debuglog.hpp>

/* This file contains the code to translate from WINDOWS-1252 (native
   charset used in English version of Morrowind) to UTF-8. The library
   is designed to be extened to support more source encodings later,
   which means that we may add support for Russian, Polish and Chinese
   files and so on.

   The code does not depend on any external library at
   runtime. Instead, it uses a pregenerated table made with iconv (see
   gen_iconv.cpp and the Makefile) which is located in tables_gen.hpp.

   This is both faster and uses less dependencies. The tables would
   only need to be regenerated if we are adding support more input
   encodings. As such, there is no need to make the generator code
   platform independent.

   The library is optimized for the case of pure ASCII input strings,
   which is the vast majority of cases at least for the English
   version. A test of my version of Morrowind.esm got 130 non-ASCII vs
   236195 ASCII strings, or less than 0.06% of strings containing
   non-ASCII characters.

   To optmize for this, ff the first pass of the string does not find
   any non-ASCII characters, the entire string is passed along without
   any modification.

   Most of the non-ASCII strings are books, and are quite large. (The
   non-ASCII characters are typically starting and ending quotation
   marks.) Within these, almost all the characters are ASCII. For this
   purpose, the library is also optimized for mostly-ASCII contents
   even in the cases where some conversion is necessary.
 */

// Generated tables
#include "tables_gen.hpp"

using namespace ToUTF8;

Utf8Encoder::Utf8Encoder(const FromType sourceEncoding):
    mOutput(50*1024)
{
    switch (sourceEncoding)
    {
        case ToUTF8::WINDOWS_1252:
        {
            translationArray = ToUTF8::windows_1252;
            break;
        }
        case ToUTF8::WINDOWS_1250:
        {
            translationArray = ToUTF8::windows_1250;
            break;
        }
        case ToUTF8::WINDOWS_1251:
        {
            translationArray = ToUTF8::windows_1251;
            break;
        }
        case ToUTF8::CP437:
        {
            translationArray = ToUTF8::cp437;
            break;
        }

        default:
        {
            assert(0);
        }
    }
}

std::string Utf8Encoder::getUtf8(const char* input, size_t size)
{
    // Double check that the input string stops at some point (it might
    // contain zero terminators before this, inside its own data, which
    // is also ok.)
    assert(input[size] == 0);

    // Note: The rest of this function is designed for single-character
    // input encodings only. It also assumes that the input encoding
    // shares its first 128 values (0-127) with ASCII. There are no plans
    // to add more encodings to this module (we are using utf8 for new
    // content files), so that shouldn't be an issue.

    // Compute output length, and check for pure ascii input at the same
    bool ascii;
    size_t outlen = getLength(input, ascii);

    // If we're pure ascii, then don't bother converting anything.
    if(ascii)
        return std::string(input, outlen);

    // Make sure the output is large enough
    resize(outlen);
    char *out = &mOutput[0];

    // Translate
    while (*input)
        copyFromArray(*(input++), out);

    // Make sure that we wrote the correct number of bytes
    assert((out-&mOutput[0]) == (int)outlen);

    // And make extra sure the output is null terminated
    assert(mOutput.size() > outlen);
    assert(mOutput[outlen] == 0);

    // Return a string
    return std::string(&mOutput[0], outlen);
}

std::string Utf8Encoder::getLegacyEnc(const char *input, size_t size)
{
    // Double check that the input string stops at some point (it might
    // contain zero terminators before this, inside its own data, which
    // is also ok.)
    assert(input[size] == 0);

    // TODO: The rest of this function is designed for single-character
    // input encodings only. It also assumes that the input the input
    // encoding shares its first 128 values (0-127) with ASCII. These
    // conditions must be checked again if you add more input encodings

    // Compute output length, and check for pure ascii input at the same
    bool ascii;
    size_t outlen = getLength2(input, ascii);

    // If we're pure ascii, then don't bother converting anything.
    if(ascii)
        return std::string(input, outlen);

    // Make sure the output is large enough
    resize(outlen);
    char *out = &mOutput[0];

    // Translate
    while(*input)
        copyFromArray2(input, out);

    // Make sure that we wrote the correct number of bytes
    assert((out-&mOutput[0]) == (int)outlen);

    // And make extra sure the output is null terminated
    assert(mOutput.size() > outlen);
    assert(mOutput[outlen] == 0);

    // Return a string
    return std::string(&mOutput[0], outlen);
}

// Make sure the output vector is large enough for 'size' bytes,
// including a terminating zero after it.

/** Get the total length length needed to decode the given string with
  the given translation array. The arrays are encoded with 6 bytes
  per character, with the first giving the length and the next 5 the
  actual data.

  The function serves a dual purpose for optimization reasons: it
  checks if the input is pure ascii (all values are <= 127). If this
  is the case, then the ascii parameter is set to true, and the
  caller can optimize for this case.
 */
size_t Utf8Encoder::getLength(const char* input, bool &ascii) const
{
    ascii = true;
    size_t len = 0;
    const char* ptr = input;
    unsigned char inp = *ptr;

    // Do away with the ascii part of the string first (this is almost
    // always the entire string.)
    while (inp && inp < 128)
        inp = *(++ptr);
    len += (ptr-input);

    // If we're not at the null terminator at this point, then there
    // were some non-ascii characters to deal with. Go to slow-mode for
    // the rest of the string.
    if (inp)
    {
        ascii = false;
        while (inp)
        {
            // Find the translated length of this character in the
            // lookup table.
            len += translationArray[inp*6];
            inp = *(++ptr);
        }
    }
    return len;
}

// Translate one character 'ch' using the translation array 'arr', and
// advance the output pointer accordingly.
void Utf8Encoder::copyFromArray(unsigned char ch, char* &out) const
{
    // Optimize for ASCII values
    if (ch < 128)
    {
        *(out++) = ch;
        return;
    }

    const signed char *in = translationArray + ch*6;
    int len = *(in++);
    memcpy(out, in, len);
    out += len;
}

size_t Utf8Encoder::getLength2(const char* input, bool &ascii) const
{
    ascii = true;
    size_t len = 0;
    const char* ptr = input;
    unsigned char inp = *ptr;

    // Do away with the ascii part of the string first (this is almost
    // always the entire string.)
    while (inp && inp < 128)
        inp = *(++ptr);
    len += (ptr-input);

    // If we're not at the null terminator at this point, then there
    // were some non-ascii characters to deal with. Go to slow-mode for
    // the rest of the string.
    if (inp)
    {
        ascii = false;
        while(inp)
        {
            len += 1;
            // Find the translated length of this character in the
            // lookup table.
            switch(inp)
            {
                case 0xe2: len -= 2; break;
                case 0xc2:
                case 0xcb:
                case 0xc4:
                case 0xc6:
                case 0xc3:
                case 0xd0:
                case 0xd1:
                case 0xd2:
                case 0xc5: len -= 1; break;
            }

            inp = *(++ptr);
        }
    }
    return len;
}

void Utf8Encoder::copyFromArray2(const char*& chp, char* &out) const
{
    unsigned char ch = *(chp++);
    // Optimize for ASCII values
    if (ch < 128)
    {
        *(out++) = ch;
        return;
    }

    int len = 1;
    switch (ch)
    {
        case 0xe2: len = 3; break;
        case 0xc2:
        case 0xcb:
        case 0xc4:
        case 0xc6:
        case 0xc3:
        case 0xd0:
        case 0xd1:
        case 0xd2:
        case 0xc5: len = 2; break;
    }

    if (len == 1) // There is no 1 length utf-8 glyph that is not 0x20 (empty space)
    {
        *(out++) = ch;
        return;
    }

    unsigned char ch2 = *(chp++);
    unsigned char ch3 = '\0';
    if (len == 3)
        ch3 = *(chp++);

    for (int i = 128; i < 256; i++)
    {
        unsigned char b1 = translationArray[i*6 + 1], b2 = translationArray[i*6 + 2], b3 = translationArray[i*6 + 3];
        if (b1 == ch && b2 == ch2 && (len != 3 || b3 == ch3))
        {
            *(out++) = (char)i;
            return;
        }
    }

    Log(Debug::Info) << "Could not find glyph " << std::hex << (int)ch << " " << (int)ch2 << " " << (int)ch3;

    *(out++) = ch; // Could not find glyph, just put whatever
}

ToUTF8::FromType ToUTF8::calculateEncoding(const std::string& encodingName)
{
    if (encodingName == "win1250")
        return ToUTF8::WINDOWS_1250;
    else if (encodingName == "win1251")
        return ToUTF8::WINDOWS_1251;
    else if (encodingName == "win1252")
        return ToUTF8::WINDOWS_1252;
    else
        throw std::runtime_error(std::string("Unknown encoding '") + encodingName + std::string("', see openmw --help for available options."));
}

std::string ToUTF8::encodingUsingMessage(const std::string& encodingName)
{
    if (encodingName == "win1250")
        return "Using Central and Eastern European font encoding.";
    else if (encodingName == "win1251")
        return "Using Cyrillic font encoding.";
    else if (encodingName == "win1252")
        return "Using default (English) font encoding.";
    else
        throw std::runtime_error(std::string("Unknown encoding '") + encodingName + std::string("', see openmw --help for available options."));
}


void insertRefCountAsserts(IRUnit& unit, IRInstruction& inst) {
  for (auto dst : inst.dsts()) {
    auto const t = dst->type();
    if (t <= TCell && t.maybe(TCounted)) {
      insertAfter(&inst,
        unit.gen(DbgAssertRefCount, inst.bcctx(), ASSERT_REASON, dst)
      );
    }
  }
}

/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
*/
#include "hphp/runtime/vm/jit/opt.h"

#include <iterator>

#include "hphp/runtime/vm/jit/ir-instruction.h"
#include "hphp/runtime/vm/jit/block.h"
#include "hphp/runtime/vm/jit/ir-unit.h"
#include "hphp/runtime/vm/jit/cfg.h"

namespace HPHP { namespace jit {

namespace {

/*
 * Insert `inst' after `definer'.
 *
 * If `definer' ends its block, it must have a fallthrough block, and `inst'
 * will be inserted at the beginning of that block, as long as the block has no
 * other predecessors.
 */
void insertAfter(IRInstruction* definer, IRInstruction* inst) {
  assertx(!definer->isTerminal());
  if (definer->isControlFlow()) {
    assertx(definer->next());
    if (definer->next()->numPreds() == 1) {
      definer->next()->prepend(inst);
    }
    return;
  }

  auto const block = definer->block();
  auto const pos = block->iteratorTo(definer);
  block->insert(std::next(pos), inst);
}

/*
 * Insert a DbgAssertRefCount instruction after each place we define a
 * maybe-refcounted SSATmp.
 */

void visit(IRUnit& unit, Block* block) {
  for (auto it = block->begin(); it != block->end();) {
    auto& inst = *it++;
    insertRefCountAsserts(unit, inst);
  }
}

}

void insertAsserts(IRUnit& unit) {
  // Note: it doesn't matter what order we visit the blocks for this pass.
  for (auto& block : poSortCfg(unit)) visit(unit, block);
}

}}


inline void UpdateManagers() {
      analysis::DefUseManager* def_use_mgr = base_->context_->get_def_use_mgr();
      // Register all new definitions.
      for (Instruction* insn : rewritten_) {
        def_use_mgr->AnalyzeInstDef(insn);
      }
      // Register all new uses.
      for (Instruction* insn : rewritten_) {
        def_use_mgr->AnalyzeInstUse(insn);
      }
    }

#include <algorithm>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "source/cfa.h"
#include "source/opt/cfg.h"
#include "source/opt/ir_builder.h"
#include "source/opt/ir_context.h"
#include "source/opt/loop_descriptor.h"
#include "source/opt/loop_utils.h"

namespace spvtools {
namespace opt {

namespace {
// Return true if |bb| is dominated by at least one block in |exits|
static inline bool DominatesAnExit(BasicBlock* bb,
                                   const std::unordered_set<BasicBlock*>& exits,
                                   const DominatorTree& dom_tree) {
  for (BasicBlock* e_bb : exits)
    if (dom_tree.Dominates(bb, e_bb)) return true;
  return false;
}

// Utility class to rewrite out-of-loop uses of an in-loop definition in terms
// of phi instructions to achieve a LCSSA form.
// For a given definition, the class user registers phi instructions using that
// definition in all loop exit blocks by which the definition escapes.
// Then, when rewriting a use of the definition, the rewriter walks the
// paths from the use the loop exits. At each step, it will insert a phi
// instruction to merge the incoming value according to exit blocks definition.
class LCSSARewriter {
 public:
  LCSSARewriter(IRContext* context, const DominatorTree& dom_tree,
                const std::unordered_set<BasicBlock*>& exit_bb,
                BasicBlock* merge_block)
      : context_(context),
        cfg_(context_->cfg()),
        dom_tree_(dom_tree),
        exit_bb_(exit_bb),
        merge_block_id_(merge_block ? merge_block->id() : 0) {}

  struct UseRewriter {
    explicit UseRewriter(LCSSARewriter* base, const Instruction& def_insn)
        : base_(base), def_insn_(def_insn) {}
    // Rewrites the use of |def_insn_| by the instruction |user| at the index
    // |operand_index| in terms of phi instruction. This recursively builds new
    // phi instructions from |user| to the loop exit blocks' phis. The use of
    // |def_insn_| in |user| is replaced by the relevant phi instruction at the
    // end of the operation.
    // It is assumed that |user| does not dominates any of the loop exit basic
    // block. This operation does not update the def/use manager, instead it
    // records what needs to be updated. The actual update is performed by
    void RewriteUse(BasicBlock* bb, Instruction* user, uint32_t operand_index) {
      assert(
          (user->opcode() != SpvOpPhi || bb != GetParent(user)) &&
          "The root basic block must be the incoming edge if |user| is a phi "
          "instruction");
      assert((user->opcode() == SpvOpPhi || bb == GetParent(user)) &&
             "The root basic block must be the instruction parent if |user| is "
             "not "
             "phi instruction");

      Instruction* new_def = GetOrBuildIncoming(bb->id());

      user->SetOperand(operand_index, {new_def->result_id()});
      rewritten_.insert(user);
    }

    // In-place update of some managers (avoid full invalidation).

   private:
    // Return the basic block that |instr| belongs to.
    BasicBlock* GetParent(Instruction* instr) {
      return base_->context_->get_instr_block(instr);
    }

    // Builds a phi instruction for the basic block |bb|. The function assumes
    // that |defining_blocks| contains the list of basic block that define the
    // usable value for each predecessor of |bb|.
    inline Instruction* CreatePhiInstruction(
        BasicBlock* bb, const std::vector<uint32_t>& defining_blocks) {
      std::vector<uint32_t> incomings;
      const std::vector<uint32_t>& bb_preds = base_->cfg_->preds(bb->id());
      assert(bb_preds.size() == defining_blocks.size());
      for (size_t i = 0; i < bb_preds.size(); i++) {
        incomings.push_back(
            GetOrBuildIncoming(defining_blocks[i])->result_id());
        incomings.push_back(bb_preds[i]);
      }
      InstructionBuilder builder(base_->context_, &*bb->begin(),
                                 IRContext::kAnalysisInstrToBlockMapping);
      Instruction* incoming_phi =
          builder.AddPhi(def_insn_.type_id(), incomings);

      rewritten_.insert(incoming_phi);
      return incoming_phi;
    }

    // Builds a phi instruction for the basic block |bb|, all incoming values
    inline Instruction* CreatePhiInstruction(BasicBlock* bb,
                                             const Instruction& value) {
      std::vector<uint32_t> incomings;
      const std::vector<uint32_t>& bb_preds = base_->cfg_->preds(bb->id());
      for (size_t i = 0; i < bb_preds.size(); i++) {
        incomings.push_back(value.result_id());
        incomings.push_back(bb_preds[i]);
      }
      InstructionBuilder builder(base_->context_, &*bb->begin(),
                                 IRContext::kAnalysisInstrToBlockMapping);
      Instruction* incoming_phi =
          builder.AddPhi(def_insn_.type_id(), incomings);

      rewritten_.insert(incoming_phi);
      return incoming_phi;
    }

    // Return the new def to use for the basic block |bb_id|.
    // If |bb_id| does not have a suitable def to use then we:
    //   - return the common def used by all predecessors;
    //   - if there is no common def, then we build a new phi instr at the
    Instruction* GetOrBuildIncoming(uint32_t bb_id) {
      assert(base_->cfg_->block(bb_id) != nullptr && "Unknown basic block");

      Instruction*& incoming_phi = bb_to_phi_[bb_id];
      if (incoming_phi) {
        return incoming_phi;
      }

      BasicBlock* bb = &*base_->cfg_->block(bb_id);
      // If this is an exit basic block, look if there already is an eligible
      // phi instruction. An eligible phi has |def_insn_| as all incoming
      if (base_->exit_bb_.count(bb)) {
        // Look if there is an eligible phi in this block.
        if (!bb->WhileEachPhiInst([&incoming_phi, this](Instruction* phi) {
              for (uint32_t i = 0; i < phi->NumInOperands(); i += 2) {
                if (phi->GetSingleWordInOperand(i) != def_insn_.result_id())
                  return true;
              }
              incoming_phi = phi;
              rewritten_.insert(incoming_phi);
              return false;
            })) {
          return incoming_phi;
        }
        incoming_phi = CreatePhiInstruction(bb, def_insn_);
        return incoming_phi;
      }

      // Get the block that defines the value to use for each predecessor.
      // If the vector has 1 value, then it means that this block does not need
      // to build a phi instruction unless |bb_id| is the loop merge block.
      const std::vector<uint32_t>& defining_blocks =
          base_->GetDefiningBlocks(bb_id);

      // Special case for structured loops: merge block might be different from
      // the exit block set. To maintain structured properties it will ease
      // transformations if the merge block also holds a phi instruction like
      // the exit ones.
      if (defining_blocks.size() > 1 || bb_id == base_->merge_block_id_) {
        if (defining_blocks.size() > 1) {
          incoming_phi = CreatePhiInstruction(bb, defining_blocks);
        } else {
          assert(bb_id == base_->merge_block_id_);
          incoming_phi =
              CreatePhiInstruction(bb, *GetOrBuildIncoming(defining_blocks[0]));
        }
      } else {
        incoming_phi = GetOrBuildIncoming(defining_blocks[0]);
      }

      return incoming_phi;
    }

    LCSSARewriter* base_;
    const Instruction& def_insn_;
    std::unordered_map<uint32_t, Instruction*> bb_to_phi_;
    std::unordered_set<Instruction*> rewritten_;
  };

 private:
  // Return the new def to use for the basic block |bb_id|.
  // If |bb_id| does not have a suitable def to use then we:
  //   - return the common def used by all predecessors;
  //   - if there is no common def, then we build a new phi instr at the
  const std::vector<uint32_t>& GetDefiningBlocks(uint32_t bb_id) {
    assert(cfg_->block(bb_id) != nullptr && "Unknown basic block");
    std::vector<uint32_t>& defining_blocks = bb_to_defining_blocks_[bb_id];

    if (defining_blocks.size()) return defining_blocks;

    // Check if one of the loop exit basic block dominates |bb_id|.
    for (const BasicBlock* e_bb : exit_bb_) {
      if (dom_tree_.Dominates(e_bb->id(), bb_id)) {
        defining_blocks.push_back(e_bb->id());
        return defining_blocks;
      }
    }

    // Process parents, they will returns their suitable blocks.
    // If they are all the same, this means this basic block is dominated by a
    // common block, so we won't need to build a phi instruction.
    for (uint32_t pred_id : cfg_->preds(bb_id)) {
      const std::vector<uint32_t>& pred_blocks = GetDefiningBlocks(pred_id);
      if (pred_blocks.size() == 1)
        defining_blocks.push_back(pred_blocks[0]);
      else
        defining_blocks.push_back(pred_id);
    }
    assert(defining_blocks.size());
    if (std::all_of(defining_blocks.begin(), defining_blocks.end(),
                    [&defining_blocks](uint32_t id) {
                      return id == defining_blocks[0];
                    })) {
      // No need for a phi.
      defining_blocks.resize(1);
    }

    return defining_blocks;
  }

  IRContext* context_;
  CFG* cfg_;
  const DominatorTree& dom_tree_;
  const std::unordered_set<BasicBlock*>& exit_bb_;
  uint32_t merge_block_id_;
  // This map represent the set of known paths. For each key, the vector
  // represent the set of blocks holding the definition to be used to build the
  // phi instruction.
  // If the vector has 0 value, then the path is unknown yet, and must be built.
  // If the vector has 1 value, then the value defined by that basic block
  //   should be used.
  // If the vector has more than 1 value, then a phi node must be created, the
  //   basic block ordering is the same as the predecessor ordering.
  std::unordered_map<uint32_t, std::vector<uint32_t>> bb_to_defining_blocks_;
};

// Make the set |blocks| closed SSA. The set is closed SSA if all the uses
// outside the set are phi instructions in exiting basic block set (hold by
inline void MakeSetClosedSSA(IRContext* context, Function* function,
                             const std::unordered_set<uint32_t>& blocks,
                             const std::unordered_set<BasicBlock*>& exit_bb,
                             LCSSARewriter* lcssa_rewriter) {
  CFG& cfg = *context->cfg();
  DominatorTree& dom_tree =
      context->GetDominatorAnalysis(function)->GetDomTree();
  analysis::DefUseManager* def_use_manager = context->get_def_use_mgr();

  for (uint32_t bb_id : blocks) {
    BasicBlock* bb = cfg.block(bb_id);
    // If bb does not dominate an exit block, then it cannot have escaping defs.
    if (!DominatesAnExit(bb, exit_bb, dom_tree)) continue;
    for (Instruction& inst : *bb) {
      LCSSARewriter::UseRewriter rewriter(lcssa_rewriter, inst);
      def_use_manager->ForEachUse(
          &inst, [&blocks, &rewriter, &exit_bb, context](
                     Instruction* use, uint32_t operand_index) {
            BasicBlock* use_parent = context->get_instr_block(use);
            assert(use_parent);
            if (blocks.count(use_parent->id())) return;

            if (use->opcode() == SpvOpPhi) {
              // If the use is a Phi instruction and the incoming block is
              // coming from the loop, then that's consistent with LCSSA form.
              if (exit_bb.count(use_parent)) {
                return;
              } else {
                // That's not an exit block, but the user is a phi instruction.
                // Consider the incoming branch only.
                use_parent = context->get_instr_block(
                    use->GetSingleWordOperand(operand_index + 1));
              }
            }
            // Rewrite the use. Note that this call does not invalidate the
            // def/use manager. So this operation is safe.
            rewriter.RewriteUse(use_parent, use, operand_index);
          });
      rewriter.UpdateManagers();
    }
  }
}

}  // namespace

void LoopUtils::CreateLoopDedicatedExits() {
  Function* function = loop_->GetHeaderBlock()->GetParent();
  LoopDescriptor& loop_desc = *context_->GetLoopDescriptor(function);
  CFG& cfg = *context_->cfg();
  analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr();

  const IRContext::Analysis PreservedAnalyses =
      IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping;

  // Gathers the set of basic block that are not in this loop and have at least
  // one predecessor in the loop and one not in the loop.
  std::unordered_set<uint32_t> exit_bb_set;
  loop_->GetExitBlocks(&exit_bb_set);

  std::unordered_set<BasicBlock*> new_loop_exits;
  bool made_change = false;
  // For each block, we create a new one that gathers all branches from
  // the loop and fall into the block.
  for (uint32_t non_dedicate_id : exit_bb_set) {
    BasicBlock* non_dedicate = cfg.block(non_dedicate_id);
    const std::vector<uint32_t>& bb_pred = cfg.preds(non_dedicate_id);
    // Ignore the block if all the predecessors are in the loop.
    if (std::all_of(bb_pred.begin(), bb_pred.end(),
                    [this](uint32_t id) { return loop_->IsInsideLoop(id); })) {
      new_loop_exits.insert(non_dedicate);
      continue;
    }

    made_change = true;
    Function::iterator insert_pt = function->begin();
    for (; insert_pt != function->end() && &*insert_pt != non_dedicate;
         ++insert_pt) {
    }
    assert(insert_pt != function->end() && "Basic Block not found");

    // Create the dedicate exit basic block.
    // TODO(1841): Handle id overflow.
    BasicBlock& exit = *insert_pt.InsertBefore(std::unique_ptr<BasicBlock>(
        new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
            context_, SpvOpLabel, 0, context_->TakeNextId(), {})))));
    exit.SetParent(function);

    // Redirect in loop predecessors to |exit| block.
    for (uint32_t exit_pred_id : bb_pred) {
      if (loop_->IsInsideLoop(exit_pred_id)) {
        BasicBlock* pred_block = cfg.block(exit_pred_id);
        pred_block->ForEachSuccessorLabel([non_dedicate, &exit](uint32_t* id) {
          if (*id == non_dedicate->id()) *id = exit.id();
        });
        // Update the CFG.
        // |non_dedicate|'s predecessor list will be updated at the end of the
        cfg.RegisterBlock(pred_block);
      }
    }

    // Register the label to the def/use manager, requires for the phi patching.
    def_use_mgr->AnalyzeInstDefUse(exit.GetLabelInst());
    context_->set_instr_block(exit.GetLabelInst(), &exit);

    InstructionBuilder builder(context_, &exit, PreservedAnalyses);
    // Now jump from our dedicate basic block to the old exit.
    // We also reset the insert point so all instructions are inserted before
    // the branch.
    builder.SetInsertPoint(builder.AddBranch(non_dedicate->id()));
    non_dedicate->ForEachPhiInst(
        [&builder, &exit, def_use_mgr, this](Instruction* phi) {
          // New phi operands for this instruction.
          std::vector<uint32_t> new_phi_op;
          // Phi operands for the dedicated exit block.
          std::vector<uint32_t> exit_phi_op;
          for (uint32_t i = 0; i < phi->NumInOperands(); i += 2) {
            uint32_t def_id = phi->GetSingleWordInOperand(i);
            uint32_t incoming_id = phi->GetSingleWordInOperand(i + 1);
            if (loop_->IsInsideLoop(incoming_id)) {
              exit_phi_op.push_back(def_id);
              exit_phi_op.push_back(incoming_id);
            } else {
              new_phi_op.push_back(def_id);
              new_phi_op.push_back(incoming_id);
            }
          }

          // Build the new phi instruction dedicated exit block.
          Instruction* exit_phi = builder.AddPhi(phi->type_id(), exit_phi_op);
          // Build the new incoming branch.
          new_phi_op.push_back(exit_phi->result_id());
          new_phi_op.push_back(exit.id());
          // Rewrite operands.
          uint32_t idx = 0;
          for (; idx < new_phi_op.size(); idx++)
            phi->SetInOperand(idx, {new_phi_op[idx]});
          // Remove extra operands, from last to first (more efficient).
          for (uint32_t j = phi->NumInOperands() - 1; j >= idx; j--)
            phi->RemoveInOperand(j);
          // Update the def/use manager for this |phi|.
          def_use_mgr->AnalyzeInstUse(phi);
        });
    // Update the CFG.
    cfg.RegisterBlock(&exit);
    cfg.RemoveNonExistingEdges(non_dedicate->id());
    new_loop_exits.insert(&exit);
    // If non_dedicate is in a loop, add the new dedicated exit in that loop.
    if (Loop* parent_loop = loop_desc[non_dedicate])
      parent_loop->AddBasicBlock(&exit);
  }

  if (new_loop_exits.size() == 1) {
    loop_->SetMergeBlock(*new_loop_exits.begin());
  }

  if (made_change) {
    context_->InvalidateAnalysesExceptFor(
        PreservedAnalyses | IRContext::kAnalysisCFG |
        IRContext::Analysis::kAnalysisLoopAnalysis);
  }
}

void LoopUtils::MakeLoopClosedSSA() {
  CreateLoopDedicatedExits();

  Function* function = loop_->GetHeaderBlock()->GetParent();
  CFG& cfg = *context_->cfg();
  DominatorTree& dom_tree =
      context_->GetDominatorAnalysis(function)->GetDomTree();

  std::unordered_set<BasicBlock*> exit_bb;
  {
    std::unordered_set<uint32_t> exit_bb_id;
    loop_->GetExitBlocks(&exit_bb_id);
    for (uint32_t bb_id : exit_bb_id) {
      exit_bb.insert(cfg.block(bb_id));
    }
  }

  LCSSARewriter lcssa_rewriter(context_, dom_tree, exit_bb,
                               loop_->GetMergeBlock());
  MakeSetClosedSSA(context_, function, loop_->GetBlocks(), exit_bb,
                   &lcssa_rewriter);

  // Make sure all defs post-dominated by the merge block have their last use no
  // further than the merge block.
  if (loop_->GetMergeBlock()) {
    std::unordered_set<uint32_t> merging_bb_id;
    loop_->GetMergingBlocks(&merging_bb_id);
    merging_bb_id.erase(loop_->GetMergeBlock()->id());
    // Reset the exit set, now only the merge block is the exit.
    exit_bb.clear();
    exit_bb.insert(loop_->GetMergeBlock());
    // LCSSARewriter is reusable here only because it forces the creation of a
    // phi instruction in the merge block.
    MakeSetClosedSSA(context_, function, merging_bb_id, exit_bb,
                     &lcssa_rewriter);
  }

  context_->InvalidateAnalysesExceptFor(
      IRContext::Analysis::kAnalysisCFG |
      IRContext::Analysis::kAnalysisDominatorAnalysis |
      IRContext::Analysis::kAnalysisLoopAnalysis);
}

Loop* LoopUtils::CloneLoop(LoopCloningResult* cloning_result) const {
  // Compute the structured order of the loop basic blocks and store it in the
  // vector ordered_loop_blocks.
  std::vector<BasicBlock*> ordered_loop_blocks;
  loop_->ComputeLoopStructuredOrder(&ordered_loop_blocks);

  // Clone the loop.
  return CloneLoop(cloning_result, ordered_loop_blocks);
}

Loop* LoopUtils::CloneAndAttachLoopToHeader(LoopCloningResult* cloning_result) {
  // Clone the loop.
  Loop* new_loop = CloneLoop(cloning_result);

  // Create a new exit block/label for the new loop.
  // TODO(1841): Handle id overflow.
  std::unique_ptr<Instruction> new_label{new Instruction(
      context_, SpvOp::SpvOpLabel, 0, context_->TakeNextId(), {})};
  std::unique_ptr<BasicBlock> new_exit_bb{new BasicBlock(std::move(new_label))};
  new_exit_bb->SetParent(loop_->GetMergeBlock()->GetParent());

  // Create an unconditional branch to the header block.
  InstructionBuilder builder{context_, new_exit_bb.get()};
  builder.AddBranch(loop_->GetHeaderBlock()->id());

  // Save the ids of the new and old merge block.
  const uint32_t old_merge_block = loop_->GetMergeBlock()->id();
  const uint32_t new_merge_block = new_exit_bb->id();

  // Replace the uses of the old merge block in the new loop with the new merge
  for (std::unique_ptr<BasicBlock>& basic_block : cloning_result->cloned_bb_) {
    for (Instruction& inst : *basic_block) {
      // For each operand in each instruction check if it is using the old merge
      // block and change it to be the new merge block.
      auto replace_merge_use = [old_merge_block,
                                new_merge_block](uint32_t* id) {
        if (*id == old_merge_block) *id = new_merge_block;
      };
      inst.ForEachInOperand(replace_merge_use);
    }
  }

  const uint32_t old_header = loop_->GetHeaderBlock()->id();
  const uint32_t new_header = new_loop->GetHeaderBlock()->id();
  analysis::DefUseManager* def_use = context_->get_def_use_mgr();

  def_use->ForEachUse(old_header,
                      [new_header, this](Instruction* inst, uint32_t operand) {
                        if (!this->loop_->IsInsideLoop(inst))
                          inst->SetOperand(operand, {new_header});
                      });

  // TODO(1841): Handle failure to create pre-header.
  def_use->ForEachUse(
      loop_->GetOrCreatePreHeaderBlock()->id(),
      [new_merge_block, this](Instruction* inst, uint32_t operand) {
        if (this->loop_->IsInsideLoop(inst))
          inst->SetOperand(operand, {new_merge_block});

      });
  new_loop->SetMergeBlock(new_exit_bb.get());

  new_loop->SetPreHeaderBlock(loop_->GetPreHeaderBlock());

  // Add the new block into the cloned instructions.
  cloning_result->cloned_bb_.push_back(std::move(new_exit_bb));

  return new_loop;
}

Loop* LoopUtils::CloneLoop(
    LoopCloningResult* cloning_result,
    const std::vector<BasicBlock*>& ordered_loop_blocks) const {
  analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr();

  std::unique_ptr<Loop> new_loop = MakeUnique<Loop>(context_);

  CFG& cfg = *context_->cfg();

  // Clone and place blocks in a SPIR-V compliant order (dominators first).
  for (BasicBlock* old_bb : ordered_loop_blocks) {
    // For each basic block in the loop, we clone it and register the mapping
    // between old and new ids.
    BasicBlock* new_bb = old_bb->Clone(context_);
    new_bb->SetParent(&function_);
    // TODO(1841): Handle id overflow.
    new_bb->GetLabelInst()->SetResultId(context_->TakeNextId());
    def_use_mgr->AnalyzeInstDef(new_bb->GetLabelInst());
    context_->set_instr_block(new_bb->GetLabelInst(), new_bb);
    cloning_result->cloned_bb_.emplace_back(new_bb);

    cloning_result->old_to_new_bb_[old_bb->id()] = new_bb;
    cloning_result->new_to_old_bb_[new_bb->id()] = old_bb;
    cloning_result->value_map_[old_bb->id()] = new_bb->id();

    if (loop_->IsInsideLoop(old_bb)) new_loop->AddBasicBlock(new_bb);

    for (auto new_inst = new_bb->begin(), old_inst = old_bb->begin();
         new_inst != new_bb->end(); ++new_inst, ++old_inst) {
      cloning_result->ptr_map_[&*new_inst] = &*old_inst;
      if (new_inst->HasResultId()) {
        // TODO(1841): Handle id overflow.
        new_inst->SetResultId(context_->TakeNextId());
        cloning_result->value_map_[old_inst->result_id()] =
            new_inst->result_id();

        // Only look at the defs for now, uses are not updated yet.
        def_use_mgr->AnalyzeInstDef(&*new_inst);
      }
    }
  }

  // All instructions (including all labels) have been cloned,
  // remap instruction operands id with the new ones.
  for (std::unique_ptr<BasicBlock>& bb_ref : cloning_result->cloned_bb_) {
    BasicBlock* bb = bb_ref.get();

    for (Instruction& insn : *bb) {
      insn.ForEachInId([cloning_result](uint32_t* old_id) {
        // If the operand is defined in the loop, remap the id.
        auto id_it = cloning_result->value_map_.find(*old_id);
        if (id_it != cloning_result->value_map_.end()) {
          *old_id = id_it->second;
        }
      });
      // Only look at what the instruction uses. All defs are register, so all
      // should be fine now.
      def_use_mgr->AnalyzeInstUse(&insn);
      context_->set_instr_block(&insn, bb);
    }
    cfg.RegisterBlock(bb);
  }

  PopulateLoopNest(new_loop.get(), *cloning_result);

  return new_loop.release();
}

void LoopUtils::PopulateLoopNest(
    Loop* new_loop, const LoopCloningResult& cloning_result) const {
  std::unordered_map<Loop*, Loop*> loop_mapping;
  loop_mapping[loop_] = new_loop;

  if (loop_->HasParent()) loop_->GetParent()->AddNestedLoop(new_loop);
  PopulateLoopDesc(new_loop, loop_, cloning_result);

  for (Loop& sub_loop :
       make_range(++TreeDFIterator<Loop>(loop_), TreeDFIterator<Loop>())) {
    Loop* cloned = new Loop(context_);
    if (Loop* parent = loop_mapping[sub_loop.GetParent()])
      parent->AddNestedLoop(cloned);
    loop_mapping[&sub_loop] = cloned;
    PopulateLoopDesc(cloned, &sub_loop, cloning_result);
  }

  loop_desc_->AddLoopNest(std::unique_ptr<Loop>(new_loop));
}

// Populates |new_loop| descriptor according to |old_loop|'s one.
void LoopUtils::PopulateLoopDesc(
    Loop* new_loop, Loop* old_loop,
    const LoopCloningResult& cloning_result) const {
  for (uint32_t bb_id : old_loop->GetBlocks()) {
    BasicBlock* bb = cloning_result.old_to_new_bb_.at(bb_id);
    new_loop->AddBasicBlock(bb);
  }
  new_loop->SetHeaderBlock(
      cloning_result.old_to_new_bb_.at(old_loop->GetHeaderBlock()->id()));
  if (old_loop->GetLatchBlock())
    new_loop->SetLatchBlock(
        cloning_result.old_to_new_bb_.at(old_loop->GetLatchBlock()->id()));
  if (old_loop->GetContinueBlock())
    new_loop->SetContinueBlock(
        cloning_result.old_to_new_bb_.at(old_loop->GetContinueBlock()->id()));
  if (old_loop->GetMergeBlock()) {
    auto it =
        cloning_result.old_to_new_bb_.find(old_loop->GetMergeBlock()->id());
    BasicBlock* bb = it != cloning_result.old_to_new_bb_.end()
                         ? it->second
                         : old_loop->GetMergeBlock();
    new_loop->SetMergeBlock(bb);
  }
  if (old_loop->GetPreHeaderBlock()) {
    auto it =
        cloning_result.old_to_new_bb_.find(old_loop->GetPreHeaderBlock()->id());
    if (it != cloning_result.old_to_new_bb_.end()) {
      new_loop->SetPreHeaderBlock(it->second);
    }
  }
}

// Class to gather some metrics about a region of interest.
void CodeMetrics::Analyze(const Loop& loop) {
  CFG& cfg = *loop.GetContext()->cfg();

  roi_size_ = 0;
  block_sizes_.clear();

  for (uint32_t id : loop.GetBlocks()) {
    const BasicBlock* bb = cfg.block(id);
    size_t bb_size = 0;
    bb->ForEachInst([&bb_size](const Instruction* insn) {
      if (insn->opcode() == SpvOpLabel) return;
      if (insn->IsNop()) return;
      if (insn->opcode() == SpvOpPhi) return;
      bb_size++;
    });
    block_sizes_[bb->id()] = bb_size;
    roi_size_ += bb_size;
  }
}

}  // namespace opt
}  // namespace spvtools


CDXLScalarBitmapIndexProbe::~CDXLScalarBitmapIndexProbe()
{
	m_dxl_index_descr->Release();
}

//	Greenplum Database
//	@filename:
//		CDXLScalarBitmapIndexProbe.cpp
//		Class for representing DXL bitmap index probe operators

#include "naucrates/dxl/operators/CDXLScalarBitmapIndexProbe.h"

#include "naucrates/dxl/operators/CDXLIndexDescr.h"
#include "naucrates/dxl/operators/CDXLNode.h"
#include "naucrates/dxl/operators/CDXLTableDescr.h"
#include "naucrates/dxl/xml/CXMLSerializer.h"
#include "naucrates/dxl/xml/dxltokens.h"

using namespace gpdxl;

//	@function:
//		Ctor
CDXLScalarBitmapIndexProbe::CDXLScalarBitmapIndexProbe(
	CMemoryPool *mp, CDXLIndexDescr *dxl_index_descr)
	: CDXLScalar(mp), m_dxl_index_descr(dxl_index_descr)
{
	GPOS_ASSERT(NULL != m_dxl_index_descr);
}

//	@function:
//		Dtor

//	@function:
//		Operator name
const CWStringConst *
CDXLScalarBitmapIndexProbe::GetOpNameStr() const
{
	return CDXLTokens::GetDXLTokenStr(EdxltokenScalarBitmapIndexProbe);
}

//	@function:
//		Serialize operator in DXL format
void
CDXLScalarBitmapIndexProbe::SerializeToDXL(CXMLSerializer *xml_serializer,
										   const CDXLNode *dxlnode) const
{
	const CWStringConst *element_name = GetOpNameStr();
	xml_serializer->OpenElement(
		CDXLTokens::GetDXLTokenStr(EdxltokenNamespacePrefix), element_name);

	// serialize children
	dxlnode->SerializeChildrenToDXL(xml_serializer);

	// serialize index descriptor
	m_dxl_index_descr->SerializeToDXL(xml_serializer);

	xml_serializer->CloseElement(
		CDXLTokens::GetDXLTokenStr(EdxltokenNamespacePrefix), element_name);
}

#ifdef GPOS_DEBUG
//	@function:
//		Checks whether operator node is well-structured
void
CDXLScalarBitmapIndexProbe::AssertValid(const CDXLNode *dxlnode,
										BOOL validate_children) const
{
	// bitmap index probe has 1 child: the index condition list
	GPOS_ASSERT(1 == dxlnode->Arity());

	if (validate_children)
	{
		CDXLNode *pdxlnIndexCondList = (*dxlnode)[0];
		GPOS_ASSERT(EdxlopScalarIndexCondList ==
					pdxlnIndexCondList->GetOperator()->GetDXLOperator());
		pdxlnIndexCondList->GetOperator()->AssertValid(pdxlnIndexCondList,
													   validate_children);
	}

	// assert validity of index descriptor
	GPOS_ASSERT(NULL != m_dxl_index_descr->MdName());
	GPOS_ASSERT(m_dxl_index_descr->MdName()->GetMDName()->IsValid());
}
#endif	// GPOS_DEBUG

// EOF


static inline double php_intpow10(int power) {
  static const double powers[] = {
    1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,
    1e8,  1e9,  1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
    1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};

  /* Not in lookup table */
  if (power < 0 || power > 22) {
    return pow(10.0, (double)power);
  }
  return powers[power];
}

static inline double php_round_helper(double value, int mode) {
  double tmp_value;

  if (value >= 0.0) {
    tmp_value = floor(value + 0.5);
    if ((mode == PHP_ROUND_HALF_DOWN && value == (-0.5 + tmp_value)) ||
        (mode == PHP_ROUND_HALF_EVEN && value == (0.5 + 2 * floor(tmp_value/2.0))) ||
        (mode == PHP_ROUND_HALF_ODD  && value == (0.5 + 2 * floor(tmp_value/2.0) - 1.0)))
    {
      tmp_value = tmp_value - 1.0;
    }
  } else {
    tmp_value = ceil(value - 0.5);
    if ((mode == PHP_ROUND_HALF_DOWN && value == (0.5 + tmp_value)) ||
        (mode == PHP_ROUND_HALF_EVEN && value == (-0.5 + 2 * ceil(tmp_value/2.0))) ||
        (mode == PHP_ROUND_HALF_ODD  && value == (-0.5 + 2 * ceil(tmp_value/2.0) + 1.0)))
    {
      tmp_value = tmp_value + 1.0;
    }
  }

  return tmp_value;
}

double php_math_round(double value, int places,
                      int mode /* = PHP_ROUND_HALF_UP */) {
  double tmp_value;

  // We need to avoid calculating log(0.0) later, but log(epsilon) is fine.
  if (std::isinf(value) || value == 0.0) {
    return value;
  }

  int precision_places = 14 - php_intlog10abs(value);
  double f1 = php_intpow10(abs(places));

  /* If the decimal precision guaranteed by FP arithmetic is higher than
   * the requested places BUT is small enough to make sure a non-zero value
   * is returned, pre-round the result to the precision */
  if (precision_places > places && precision_places - places < 15) {
    double f2 = php_intpow10(abs(precision_places));
    if (precision_places >= 0) {
      tmp_value = value * f2;
    } else {
      tmp_value = value / f2;
    }
    /* preround the result (tmp_value will always be something * 1e14,
     * thus never larger than 1e15 here) */
    tmp_value = php_round_helper(tmp_value, mode);
    /* now correctly move the decimal point */
    f2 = php_intpow10(abs(places - precision_places));
    /* because places < precision_places */
    tmp_value = tmp_value / f2;
  } else {
    /* adjust the value */
    if (places >= 0) {
      tmp_value = value * f1;
    } else {
      tmp_value = value / f1;
    }
    /* This value is beyond our precision, so rounding it is pointless */
    if (fabs(tmp_value) >= 1e15) {
      return value;
    }
  }

  /* round the temp value */
  tmp_value = php_round_helper(tmp_value, mode);

  /* see if it makes sense to use simple division to round the value */
  if (abs(places) < 23) {
    if (places > 0) {
      tmp_value /= f1;
    } else {
      tmp_value *= f1;
    }
  } else {
    /* Simple division can't be used since that will cause wrong results.
     * Instead, the number is converted to a string and back again using
     * strtod(). strtod() will return the nearest possible FP value for
     * that string. */

    /* 40 Bytes should be more than enough for this format string. The
     * float won't be larger than 1e15 anyway. But just in case, use
     * snprintf() and make sure the buffer is zero-terminated */
    char buf[40];
    snprintf(buf, 39, "%15fe%d", tmp_value, -places);
    buf[39] = '\0';
    tmp_value = strtod(buf, nullptr);

    /* couldn't convert to string and back */
    if (std::isinf(tmp_value)) {
      tmp_value = value;
    }
  }

  return tmp_value;
}

}


void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) {
  P = getInfo(Id).Phases;
  assert(0 < P.size() && "Not enough phases in list");
  assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list");
}

//===--- Types.cpp - Driver input & temporary type information ------------===//

#include "clang/Driver/Types.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/Arg.h"
#include <cassert>
#include <cstring>

using namespace clang::driver;
using namespace clang::driver::types;

struct TypeInfo {
  const char *Name;
  const char *TempSuffix;
  ID PreprocessedType;
  const llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> Phases;
};

static const TypeInfo TypeInfos[] = {
#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, ...) \
  { NAME, TEMP_SUFFIX, TY_##PP_TYPE, { __VA_ARGS__ }, },
#include "clang/Driver/Types.def"
#undef TYPE
};
static const unsigned numTypes = llvm::array_lengthof(TypeInfos);

static const TypeInfo &getInfo(unsigned id) {
  assert(id > 0 && id - 1 < numTypes && "Invalid Type ID.");
  return TypeInfos[id - 1];
}

const char *types::getTypeName(ID Id) {
  return getInfo(Id).Name;
}

types::ID types::getPreprocessedType(ID Id) {
  ID PPT = getInfo(Id).PreprocessedType;
  assert((llvm::is_contained(getInfo(Id).Phases, phases::Preprocess) !=
          (PPT == TY_INVALID)) &&
         "Unexpected Preprocess Type.");
  return PPT;
}

static bool isPrepeocessedModuleType(ID Id) {
  return Id == TY_CXXModule || Id == TY_PP_CXXModule;
}

types::ID types::getPrecompiledType(ID Id) {
  if (isPrepeocessedModuleType(Id))
    return TY_ModuleFile;
  if (onlyPrecompileType(Id))
    return TY_PCH;
  return TY_INVALID;
}

const char *types::getTypeTempSuffix(ID Id, bool CLMode) {
  if (CLMode) {
    switch (Id) {
    case TY_Object:
    case TY_LTO_BC:
      return "obj";
    case TY_Image:
      return "exe";
    case TY_PP_Asm:
      return "asm";
    default:
      break;
    }
  }
  return getInfo(Id).TempSuffix;
}

bool types::onlyAssembleType(ID Id) {
  return llvm::is_contained(getInfo(Id).Phases, phases::Assemble) &&
         !llvm::is_contained(getInfo(Id).Phases, phases::Compile) &&
         !llvm::is_contained(getInfo(Id).Phases, phases::Backend);
}

bool types::onlyPrecompileType(ID Id) {
  return llvm::is_contained(getInfo(Id).Phases, phases::Precompile) &&
         !isPrepeocessedModuleType(Id);
}

bool types::canTypeBeUserSpecified(ID Id) {
  static const clang::driver::types::ID kStaticLangageTypes[] = {
      TY_CUDA_DEVICE,   TY_HIP_DEVICE,    TY_PP_CHeader,
      TY_PP_ObjCHeader, TY_PP_CXXHeader,  TY_PP_ObjCXXHeader,
      TY_PP_CXXModule,  TY_LTO_IR,        TY_LTO_BC,
      TY_Plist,         TY_RewrittenObjC, TY_RewrittenLegacyObjC,
      TY_Remap,         TY_PCH,           TY_Object,
      TY_Image,         TY_dSYM,          TY_Dependencies,
      TY_CUDA_FATBIN,   TY_HIP_FATBIN};
  return !llvm::is_contained(kStaticLangageTypes, Id);
}

bool types::appendSuffixForType(ID Id) {
  return Id == TY_PCH || Id == TY_dSYM || Id == TY_CUDA_FATBIN ||
         Id == TY_HIP_FATBIN;
}

bool types::canLipoType(ID Id) {
  return (Id == TY_Nothing ||
          Id == TY_Image ||
          Id == TY_Object ||
          Id == TY_LTO_BC);
}

bool types::isAcceptedByClang(ID Id) {
  switch (Id) {
  default:
    return false;

  case TY_Asm:
  case TY_C: case TY_PP_C:
  case TY_CL:
  case TY_CUDA: case TY_PP_CUDA:
  case TY_CUDA_DEVICE:
  case TY_HIP:
  case TY_PP_HIP:
  case TY_HIP_DEVICE:
  case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
  case TY_CXX: case TY_PP_CXX:
  case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
  case TY_CHeader: case TY_PP_CHeader:
  case TY_CLHeader:
  case TY_ObjCHeader: case TY_PP_ObjCHeader:
  case TY_CXXHeader: case TY_PP_CXXHeader:
  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
  case TY_CXXModule: case TY_PP_CXXModule:
  case TY_AST: case TY_ModuleFile:
  case TY_LLVM_IR: case TY_LLVM_BC:
    return true;
  }
}

bool types::isObjC(ID Id) {
  switch (Id) {
  default:
    return false;

  case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
  case TY_ObjCXX: case TY_PP_ObjCXX:
  case TY_ObjCHeader: case TY_PP_ObjCHeader:
  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_PP_ObjCXX_Alias:
    return true;
  }
}

bool types::isCXX(ID Id) {
  switch (Id) {
  default:
    return false;

  case TY_CXX: case TY_PP_CXX:
  case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
  case TY_CXXHeader: case TY_PP_CXXHeader:
  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
  case TY_CXXModule: case TY_PP_CXXModule:
  case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE:
  case TY_HIP:
  case TY_PP_HIP:
  case TY_HIP_DEVICE:
    return true;
  }
}

bool types::isLLVMIR(ID Id) {
  switch (Id) {
  default:
    return false;

  case TY_LLVM_IR:
  case TY_LLVM_BC:
  case TY_LTO_IR:
  case TY_LTO_BC:
    return true;
  }
}

bool types::isCuda(ID Id) {
  switch (Id) {
  default:
    return false;

  case TY_CUDA:
  case TY_PP_CUDA:
  case TY_CUDA_DEVICE:
    return true;
  }
}

bool types::isHIP(ID Id) {
  switch (Id) {
  default:
    return false;

  case TY_HIP:
  case TY_PP_HIP:
  case TY_HIP_DEVICE:
    return true;
  }
}

bool types::isSrcFile(ID Id) {
  return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
}

types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
  return llvm::StringSwitch<types::ID>(Ext)
           .Case("c", TY_C)
           .Case("C", TY_CXX)
           .Case("F", TY_Fortran)
           .Case("f", TY_PP_Fortran)
           .Case("h", TY_CHeader)
           .Case("H", TY_CXXHeader)
           .Case("i", TY_PP_C)
           .Case("m", TY_ObjC)
           .Case("M", TY_ObjCXX)
           .Case("o", TY_Object)
           .Case("S", TY_Asm)
           .Case("s", TY_PP_Asm)
           .Case("bc", TY_LLVM_BC)
           .Case("cc", TY_CXX)
           .Case("CC", TY_CXX)
           .Case("cl", TY_CL)
           .Case("cp", TY_CXX)
           .Case("cu", TY_CUDA)
           .Case("hh", TY_CXXHeader)
           .Case("ii", TY_PP_CXX)
           .Case("ll", TY_LLVM_IR)
           .Case("mi", TY_PP_ObjC)
           .Case("mm", TY_ObjCXX)
           .Case("rs", TY_RenderScript)
           .Case("adb", TY_Ada)
           .Case("ads", TY_Ada)
           .Case("asm", TY_PP_Asm)
           .Case("ast", TY_AST)
           .Case("ccm", TY_CXXModule)
           .Case("cpp", TY_CXX)
           .Case("CPP", TY_CXX)
           .Case("c++", TY_CXX)
           .Case("C++", TY_CXX)
           .Case("cui", TY_PP_CUDA)
           .Case("cxx", TY_CXX)
           .Case("CXX", TY_CXX)
           .Case("F90", TY_Fortran)
           .Case("f90", TY_PP_Fortran)
           .Case("F95", TY_Fortran)
           .Case("f95", TY_PP_Fortran)
           .Case("for", TY_PP_Fortran)
           .Case("FOR", TY_PP_Fortran)
           .Case("fpp", TY_Fortran)
           .Case("FPP", TY_Fortran)
           .Case("gch", TY_PCH)
           .Case("hip", TY_HIP)
           .Case("hpp", TY_CXXHeader)
           .Case("iim", TY_PP_CXXModule)
           .Case("lib", TY_Object)
           .Case("mii", TY_PP_ObjCXX)
           .Case("obj", TY_Object)
           .Case("ifs", TY_IFS)
           .Case("pch", TY_PCH)
           .Case("pcm", TY_ModuleFile)
           .Case("c++m", TY_CXXModule)
           .Case("cppm", TY_CXXModule)
           .Case("cxxm", TY_CXXModule)
           .Default(TY_INVALID);
}

types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
  for (unsigned i=0; i<numTypes; ++i) {
    types::ID Id = (types::ID) (i + 1);
    if (canTypeBeUserSpecified(Id) &&
        strcmp(Name, getInfo(Id).Name) == 0)
      return Id;
  }

  return TY_INVALID;
}

// FIXME: Why don't we just put this list in the defs file, eh.
// FIXME: The list is now in Types.def but for now this function will verify
//        the old behavior and a subsequent change will delete most of the body.

void types::getCompilationPhases(const clang::driver::Driver &Driver,
                                 llvm::opt::DerivedArgList &DAL, ID Id,
                                 llvm::SmallVectorImpl<phases::ID> &P) {
  llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PhaseList;
  types::getCompilationPhases(Id, PhaseList);

  // Filter to compiler mode. When the compiler is run as a preprocessor then
  // compilation is not an option.
  // -S runs the compiler in Assembly listing mode.
  if (Driver.CCCIsCPP() || DAL.getLastArg(options::OPT_E) ||
      DAL.getLastArg(options::OPT__SLASH_EP) ||
      DAL.getLastArg(options::OPT_M, options::OPT_MM) ||
      DAL.getLastArg(options::OPT__SLASH_P))
    llvm::copy_if(PhaseList, std::back_inserter(P),
                  [](phases::ID Phase) { return Phase <= phases::Preprocess; });

  // --precompile only runs up to precompilation.
  // This is a clang extension and is not compatible with GCC.
  else if (DAL.getLastArg(options::OPT__precompile))
    llvm::copy_if(PhaseList, std::back_inserter(P),
                  [](phases::ID Phase) { return Phase <= phases::Precompile; });

  // Treat Interface Stubs like its own compilation mode.
  else if (DAL.getLastArg(options::OPT_emit_interface_stubs)) {
    llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> IfsModePhaseList;
    llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> &PL = PhaseList;
    phases::ID LastPhase = phases::IfsMerge;
    if (Id != types::TY_IFS) {
      if (DAL.hasArg(options::OPT_c))
        LastPhase = phases::Compile;
      PL = IfsModePhaseList;
      types::getCompilationPhases(types::TY_IFS_CPP, PL);
    }
    llvm::copy_if(PL, std::back_inserter(P), [&](phases::ID Phase) {
      return Phase <= LastPhase;
    });
  }

  // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
  else if (DAL.getLastArg(options::OPT_fsyntax_only) ||
           DAL.getLastArg(options::OPT_print_supported_cpus) ||
           DAL.getLastArg(options::OPT_module_file_info) ||
           DAL.getLastArg(options::OPT_verify_pch) ||
           DAL.getLastArg(options::OPT_rewrite_objc) ||
           DAL.getLastArg(options::OPT_rewrite_legacy_objc) ||
           DAL.getLastArg(options::OPT__migrate) ||
           DAL.getLastArg(options::OPT__analyze) ||
           DAL.getLastArg(options::OPT_emit_ast))
    llvm::copy_if(PhaseList, std::back_inserter(P),
                  [](phases::ID Phase) { return Phase <= phases::Compile; });

  else if (DAL.getLastArg(options::OPT_S) ||
           DAL.getLastArg(options::OPT_emit_llvm))
    llvm::copy_if(PhaseList, std::back_inserter(P),
                  [](phases::ID Phase) { return Phase <= phases::Backend; });

  else if (DAL.getLastArg(options::OPT_c))
    llvm::copy_if(PhaseList, std::back_inserter(P),
                  [](phases::ID Phase) { return Phase <= phases::Assemble; });

  // Generally means, do every phase until Link.
  else
    P = PhaseList;
}

ID types::lookupCXXTypeForCType(ID Id) {
  switch (Id) {
  default:
    return Id;

  case types::TY_C:
    return types::TY_CXX;
  case types::TY_PP_C:
    return types::TY_PP_CXX;
  case types::TY_CHeader:
    return types::TY_CXXHeader;
  case types::TY_PP_CHeader:
    return types::TY_PP_CXXHeader;
  }
}

ID types::lookupHeaderTypeForSourceType(ID Id) {
  switch (Id) {
  default:
    return Id;

  // FIXME: Handle preprocessed input types.
  case types::TY_C:
    return types::TY_CHeader;
  case types::TY_CXX:
  case types::TY_CXXModule:
    return types::TY_CXXHeader;
  case types::TY_ObjC:
    return types::TY_ObjCHeader;
  case types::TY_ObjCXX:
    return types::TY_ObjCXXHeader;
  case types::TY_CL:
    return types::TY_CLHeader;
  }
}


int Trick::MonteCarlo::execute_monte() {

    if (enabled) {
        if (is_master()) {
            if (master_init() != 0) {
                message_publish(MSG_ERROR, "Monte : An error occurred during Monte Carlo initialization. Exiting.\n") ;
                exit(0);
            }
            master();
        } else {
            slave_init();
            execute_as_slave();
        }
    }
    return(0);
}

#include <sys/resource.h>

#include "trick/MonteCarlo.hh"
#include "trick/message_proto.h"
#include "trick/message_type.h"

/** @par Detailed Design: */