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

#include "util/thread/worker_thread.h"

#include "gtest/gtest.h"
#include "util/misc/clock.h"
#include "util/synchronization/semaphore.h"

namespace crashpad {
namespace test {
namespace {

constexpr uint64_t kNanosecondsPerSecond = static_cast<uint64_t>(1E9);

class WorkDelegate : public WorkerThread::Delegate {
 public:
  WorkDelegate() {}
  ~WorkDelegate() {}

  void DoWork(const WorkerThread* thread) override {
    if (work_count_ < waiting_for_count_) {
      if (++work_count_ == waiting_for_count_) {
        semaphore_.Signal();
      }
    }
  }

  void SetDesiredWorkCount(int times) {
    waiting_for_count_ = times;
  }

  //! \brief Suspends the calling thread until the DoWork() has been called
  //!     the number of times specified by SetDesiredWorkCount().
  void WaitForWorkCount() {
    semaphore_.Wait();
  }

  int work_count() const { return work_count_; }

 private:
  Semaphore semaphore_{0};
  int work_count_ = 0;
  int waiting_for_count_ = -1;

  DISALLOW_COPY_AND_ASSIGN(WorkDelegate);
};

TEST(WorkerThread, DoWork) {
  WorkDelegate delegate;
  WorkerThread thread(0.05, &delegate);

  uint64_t start = ClockMonotonicNanoseconds();

  delegate.SetDesiredWorkCount(2);
  thread.Start(0);
  EXPECT_TRUE(thread.is_running());

  delegate.WaitForWorkCount();
  thread.Stop();
  EXPECT_FALSE(thread.is_running());

  EXPECT_GE(1 * kNanosecondsPerSecond, ClockMonotonicNanoseconds() - start);
}

TEST(WorkerThread, StopBeforeDoWork) {
  WorkDelegate delegate;
  WorkerThread thread(1, &delegate);

  thread.Start(15);
  thread.Stop();

  EXPECT_EQ(delegate.work_count(), 0);
}

TEST(WorkerThread, Restart) {
  WorkDelegate delegate;
  WorkerThread thread(0.05, &delegate);

  delegate.SetDesiredWorkCount(1);
  thread.Start(0);
  EXPECT_TRUE(thread.is_running());

  delegate.WaitForWorkCount();
  thread.Stop();
  ASSERT_FALSE(thread.is_running());

  delegate.SetDesiredWorkCount(2);
  thread.Start(0);
  delegate.WaitForWorkCount();
  thread.Stop();
  ASSERT_FALSE(thread.is_running());
}

TEST(WorkerThread, DoWorkNow) {
  WorkDelegate delegate;
  WorkerThread thread(100, &delegate);

  uint64_t start = ClockMonotonicNanoseconds();

  delegate.SetDesiredWorkCount(1);
  thread.Start(0);
  EXPECT_TRUE(thread.is_running());

  delegate.WaitForWorkCount();
  EXPECT_EQ(delegate.work_count(), 1);

  delegate.SetDesiredWorkCount(2);
  thread.DoWorkNow();
  delegate.WaitForWorkCount();
  thread.Stop();
  EXPECT_EQ(delegate.work_count(), 2);

  EXPECT_GE(100 * kNanosecondsPerSecond, ClockMonotonicNanoseconds() - start);
}

TEST(WorkerThread, DoWorkNowAtStart) {
  WorkDelegate delegate;
  WorkerThread thread(100, &delegate);

  uint64_t start = ClockMonotonicNanoseconds();

  delegate.SetDesiredWorkCount(1);
  thread.Start(100);
  EXPECT_TRUE(thread.is_running());

  thread.DoWorkNow();
  delegate.WaitForWorkCount();
  EXPECT_EQ(delegate.work_count(), 1);

  EXPECT_GE(100 * kNanosecondsPerSecond, ClockMonotonicNanoseconds() - start);

  thread.Stop();
  EXPECT_FALSE(thread.is_running());
}

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

#include "util/thread/worker_thread.h"

#include "gtest/gtest.h"
#include "util/misc/clock.h"
#include "util/synchronization/semaphore.h"

namespace crashpad {
namespace test {
namespace {

constexpr uint64_t kNanosecondsPerSecond = static_cast<uint64_t>(1E9);

class WorkDelegate : public WorkerThread::Delegate {
 public:
  WorkDelegate() {}
  ~WorkDelegate() {}

  void DoWork(const WorkerThread* thread) override {
    if (work_count_ < waiting_for_count_) {
      if (++work_count_ == waiting_for_count_) {
        semaphore_.Signal();
      }
    }
  }

  void SetDesiredWorkCount(int times) {
    waiting_for_count_ = times;
  }

  //! \brief Suspends the calling thread until the DoWork() has been called
  //!     the number of times specified by SetDesiredWorkCount().
  void WaitForWorkCount() {
    semaphore_.Wait();
  }

  int work_count() const { return work_count_; }

 private:
  Semaphore semaphore_{0};
  int work_count_ = 0;
  int waiting_for_count_ = -1;

  DISALLOW_COPY_AND_ASSIGN(WorkDelegate);
};

TEST(WorkerThread, DoWork) {
  WorkDelegate delegate;
  WorkerThread thread(0.05, &delegate);

  uint64_t start = ClockMonotonicNanoseconds();

  delegate.SetDesiredWorkCount(2);
  thread.Start(0);
  EXPECT_TRUE(thread.is_running());

  delegate.WaitForWorkCount();
  thread.Stop();
  EXPECT_FALSE(thread.is_running());

// Fuchsia's scheduler is very antagonistic. The assumption that the two work
// items complete in some particular amount of time is strictly incorrect, but
// also somewhat useful. The expected time "should" be ~40-50ms with a work
// interval of 0.05s, but on Fuchsia, 1200ms was observed. So, on Fuchsia, use a
// much larger timeout. See https://crashpad.chromium.org/bug/231.
#if defined(OS_FUCHSIA)
  constexpr uint64_t kUpperBoundTime = 10;
#else
  constexpr uint64_t kUpperBoundTime = 1;
#endif
  EXPECT_GE(kUpperBoundTime * kNanosecondsPerSecond,
            ClockMonotonicNanoseconds() - start);
}

TEST(WorkerThread, StopBeforeDoWork) {
  WorkDelegate delegate;
  WorkerThread thread(1, &delegate);

  thread.Start(15);
  thread.Stop();

  EXPECT_EQ(delegate.work_count(), 0);
}

TEST(WorkerThread, Restart) {
  WorkDelegate delegate;
  WorkerThread thread(0.05, &delegate);

  delegate.SetDesiredWorkCount(1);
  thread.Start(0);
  EXPECT_TRUE(thread.is_running());

  delegate.WaitForWorkCount();
  thread.Stop();
  ASSERT_FALSE(thread.is_running());

  delegate.SetDesiredWorkCount(2);
  thread.Start(0);
  delegate.WaitForWorkCount();
  thread.Stop();
  ASSERT_FALSE(thread.is_running());
}

TEST(WorkerThread, DoWorkNow) {
  WorkDelegate delegate;
  WorkerThread thread(100, &delegate);

  uint64_t start = ClockMonotonicNanoseconds();

  delegate.SetDesiredWorkCount(1);
  thread.Start(0);
  EXPECT_TRUE(thread.is_running());

  delegate.WaitForWorkCount();
  EXPECT_EQ(delegate.work_count(), 1);

  delegate.SetDesiredWorkCount(2);
  thread.DoWorkNow();
  delegate.WaitForWorkCount();
  thread.Stop();
  EXPECT_EQ(delegate.work_count(), 2);

  EXPECT_GE(100 * kNanosecondsPerSecond, ClockMonotonicNanoseconds() - start);
}

TEST(WorkerThread, DoWorkNowAtStart) {
  WorkDelegate delegate;
  WorkerThread thread(100, &delegate);

  uint64_t start = ClockMonotonicNanoseconds();

  delegate.SetDesiredWorkCount(1);
  thread.Start(100);
  EXPECT_TRUE(thread.is_running());

  thread.DoWorkNow();
  delegate.WaitForWorkCount();
  EXPECT_EQ(delegate.work_count(), 1);

  EXPECT_GE(100 * kNanosecondsPerSecond, ClockMonotonicNanoseconds() - start);

  thread.Stop();
  EXPECT_FALSE(thread.is_running());
}

}  // namespace
}  // namespace test
}  // namespace crashpad
<|endoftext|>


<commit_before>//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//

#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
       I != E; ++I) {
    Record *R = *I;
    if (R->getName() == "PHI" || R->getName() == "INLINEASM") continue;

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    unsigned numBits = BI->getNumBits();
    BitsInit *NewBI = new BitsInit(numBits);
    for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
      unsigned bitSwapIdx = numBits - bit - 1;
      Init *OrigBit = BI->getBit(bit);
      Init *BitSwap = BI->getBit(bitSwapIdx);
      NewBI->setBit(bit, BitSwap);
      NewBI->setBit(bitSwapIdx, OrigBit);
    }
    if (numBits % 2) {
      unsigned middle = (numBits + 1) / 2;
      NewBI->setBit(middle, BI->getBit(middle));
    }

    // Update the bits in reversed order so that emitInstrOpBits will get the
    // correct endianness.
    R->getValue("Inst")->setValue(NewBI);
  }
}

// If the VarBitInit at position 'bit' matches the specified variable then
// return the variable bit position.  Otherwise return -1.
int CodeEmitterGen::getVariableBit(const std::string &VarName,
            BitsInit *BI, int bit) {
  if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) {
    TypedInit *TI = VBI->getVariable();

    if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
      if (VI->getName() == VarName) return VBI->getBitNum();
    }
  }

  return -1;
}

void CodeEmitterGen::run(std::ostream &o) {
  CodeGenTarget Target;
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  // For little-endian instruction bit encodings, reverse the bit order
  if (Target.isLittleEndianEncoding()) reverseBits(Insts);

  EmitSourceFileHeader("Machine Code Emitter", o);
  std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";

  std::vector<const CodeGenInstruction*> NumberedInstructions;
  Target.getInstructionsByEnumValue(NumberedInstructions);

  // Emit function declaration
  o << "unsigned " << Target.getName() << "CodeEmitter::"
    << "getBinaryCodeForInstr(MachineInstr &MI) {\n";

  // Emit instruction base values
  o << "  static const unsigned InstBits[] = {\n";
  for (std::vector<const CodeGenInstruction*>::iterator
          IN = NumberedInstructions.begin(),
          EN = NumberedInstructions.end();
       IN != EN; ++IN) {
    const CodeGenInstruction *CGI = *IN;
    Record *R = CGI->TheDef;

    if (IN != NumberedInstructions.begin()) o << ",\n";

    if (R->getName() == "PHI" || R->getName() == "INLINEASM") {
      o << "    0U";
      continue;
    }

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    unsigned Value = 0;
    const std::vector<RecordVal> &Vals = R->getValues();

    // Start by filling in fixed values...
    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
      if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
        Value |= B->getValue() << (e-i-1);
      }
    }
    o << "    " << Value << "U";
  }
  o << "\n  };\n";

  // Map to accumulate all the cases.
  std::map<std::string, std::vector<std::string> > CaseMap;

  // Construct all cases statement for each opcode
  for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
        IC != EC; ++IC) {
    Record *R = *IC;
    const std::string &InstName = R->getName();
    std::string Case("");

    if (InstName == "PHI" || InstName == "INLINEASM") continue;

    BitsInit *BI = R->getValueAsBitsInit("Inst");
    const std::vector<RecordVal> &Vals = R->getValues();

    // Loop over all of the fields in the instruction, determining which are the
    // operands to the instruction.
    unsigned op = 0;
    for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
      if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
        // Is the operand continuous? If so, we can just mask and OR it in
        // instead of doing it bit-by-bit, saving a lot in runtime cost.
        const std::string &VarName = Vals[i].getName();
        bool gotOp = false;

        for (int bit = BI->getNumBits()-1; bit >= 0; ) {
          int varBit = getVariableBit(VarName, BI, bit);

          if (varBit == -1) {
            --bit;
          } else {
            int beginInstBit = bit;
            int beginVarBit = varBit;
            int N = 1;

            for (--bit; bit >= 0;) {
              varBit = getVariableBit(VarName, BI, bit);
              if (varBit == -1 || varBit != (beginVarBit - N)) break;
              ++N;
              --bit;
            }

            if (!gotOp) {
              Case += "      // op: " + VarName + "\n"
                   +  "      op = getMachineOpValue(MI, MI.getOperand("
                   +  utostr(op++)
                   +  "));\n";
              gotOp = true;
            }

            unsigned opMask = (1 << N) - 1;
            int opShift = beginVarBit - N + 1;
            opMask <<= opShift;
            opShift = beginInstBit - beginVarBit;

            if (opShift > 0) {
              Case += "      Value |= (op & " + utostr(opMask) + "U) << "
                   +  itostr(opShift) + ";\n";
            } else if (opShift < 0) {
              Case += "      Value |= (op & " + utostr(opMask) + "U) >> "
                   +  itostr(-opShift) + ";\n";
            } else {
              Case += "      Value |= op & " + utostr(opMask) + "U;\n";
            }
          }
        }
      }
    }

    std::vector<std::string> &InstList =  CaseMap[Case];
    InstList.push_back(InstName);
  }

  // Emit initial function code
  o << "  const unsigned opcode = MI.getOpcode();\n"
    << "  unsigned Value = InstBits[opcode];\n"
    << "  unsigned op;\n"
    << "  switch (opcode) {\n";

  // Emit each case statement
  std::map<std::string, std::vector<std::string> >::iterator IE, EE;
  for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
    const std::string &Case = IE->first;
    std::vector<std::string> &InstList = IE->second;

    for (int i = 0, N = InstList.size(); i < N; i++) {
      if (i) o << "\n";
      o << "    case " << Namespace << InstList[i]  << ":";
    }
    o << " {\n";
    o << Case;
    o << "      break;\n"
      << "    }\n";
  }

  // Default case: unhandled opcode
  o << "  default:\n"
    << "    std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
    << "    abort();\n"
    << "  }\n"
    << "  return Value;\n"
    << "}\n\n";
}
<commit_msg>Fix JIT encoding of two-addr instructions.<commit_after>//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//

#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
       I != E; ++I) {
    Record *R = *I;
    if (R->getName() == "PHI" || R->getName() == "INLINEASM") continue;

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    unsigned numBits = BI->getNumBits();
    BitsInit *NewBI = new BitsInit(numBits);
    for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
      unsigned bitSwapIdx = numBits - bit - 1;
      Init *OrigBit = BI->getBit(bit);
      Init *BitSwap = BI->getBit(bitSwapIdx);
      NewBI->setBit(bit, BitSwap);
      NewBI->setBit(bitSwapIdx, OrigBit);
    }
    if (numBits % 2) {
      unsigned middle = (numBits + 1) / 2;
      NewBI->setBit(middle, BI->getBit(middle));
    }

    // Update the bits in reversed order so that emitInstrOpBits will get the
    // correct endianness.
    R->getValue("Inst")->setValue(NewBI);
  }
}

// If the VarBitInit at position 'bit' matches the specified variable then
// return the variable bit position.  Otherwise return -1.
int CodeEmitterGen::getVariableBit(const std::string &VarName,
            BitsInit *BI, int bit) {
  if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) {
    TypedInit *TI = VBI->getVariable();

    if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
      if (VI->getName() == VarName) return VBI->getBitNum();
    }
  }

  return -1;
}

void CodeEmitterGen::run(std::ostream &o) {
  CodeGenTarget Target;
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  // For little-endian instruction bit encodings, reverse the bit order
  if (Target.isLittleEndianEncoding()) reverseBits(Insts);

  EmitSourceFileHeader("Machine Code Emitter", o);
  std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";

  std::vector<const CodeGenInstruction*> NumberedInstructions;
  Target.getInstructionsByEnumValue(NumberedInstructions);

  // Emit function declaration
  o << "unsigned " << Target.getName() << "CodeEmitter::"
    << "getBinaryCodeForInstr(MachineInstr &MI) {\n";

  // Emit instruction base values
  o << "  static const unsigned InstBits[] = {\n";
  for (std::vector<const CodeGenInstruction*>::iterator
          IN = NumberedInstructions.begin(),
          EN = NumberedInstructions.end();
       IN != EN; ++IN) {
    const CodeGenInstruction *CGI = *IN;
    Record *R = CGI->TheDef;

    if (IN != NumberedInstructions.begin()) o << ",\n";

    if (R->getName() == "PHI" || R->getName() == "INLINEASM") {
      o << "    0U";
      continue;
    }

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    unsigned Value = 0;
    const std::vector<RecordVal> &Vals = R->getValues();

    // Start by filling in fixed values...
    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
      if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
        Value |= B->getValue() << (e-i-1);
      }
    }
    o << "    " << Value << "U";
  }
  o << "\n  };\n";

  // Map to accumulate all the cases.
  std::map<std::string, std::vector<std::string> > CaseMap;

  // Construct all cases statement for each opcode
  for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
        IC != EC; ++IC) {
    Record *R = *IC;
    const std::string &InstName = R->getName();
    std::string Case("");

    if (InstName == "PHI" || InstName == "INLINEASM") continue;

    BitsInit *BI = R->getValueAsBitsInit("Inst");
    const std::vector<RecordVal> &Vals = R->getValues();

    // Loop over all of the fields in the instruction, determining which are the
    // operands to the instruction.
    unsigned op = 0;
    for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
      if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
        // Is the operand continuous? If so, we can just mask and OR it in
        // instead of doing it bit-by-bit, saving a lot in runtime cost.
        const std::string &VarName = Vals[i].getName();
        bool gotOp = false;

        for (int bit = BI->getNumBits()-1; bit >= 0; ) {
          int varBit = getVariableBit(VarName, BI, bit);

          if (varBit == -1) {
            --bit;
          } else {
            int beginInstBit = bit;
            int beginVarBit = varBit;
            int N = 1;

            for (--bit; bit >= 0;) {
              varBit = getVariableBit(VarName, BI, bit);
              if (varBit == -1 || varBit != (beginVarBit - N)) break;
              ++N;
              --bit;
            }

            if (!gotOp) {
              Case += "      // op: " + VarName + "\n"
                   +  "      op = getMachineOpValue(MI, MI.getOperand("
                   +  utostr(op++)
                   +  "));\n";
              gotOp = true;

              // If this is a two-address instruction and we just got the dest
              // op, skip the src op.
              if (op == 1 && Target.getInstruction(InstName).isTwoAddress)
                ++op;
            }

            unsigned opMask = (1 << N) - 1;
            int opShift = beginVarBit - N + 1;
            opMask <<= opShift;
            opShift = beginInstBit - beginVarBit;

            if (opShift > 0) {
              Case += "      Value |= (op & " + utostr(opMask) + "U) << "
                   +  itostr(opShift) + ";\n";
            } else if (opShift < 0) {
              Case += "      Value |= (op & " + utostr(opMask) + "U) >> "
                   +  itostr(-opShift) + ";\n";
            } else {
              Case += "      Value |= op & " + utostr(opMask) + "U;\n";
            }
          }
        }
      }
    }

    std::vector<std::string> &InstList =  CaseMap[Case];
    InstList.push_back(InstName);
  }

  // Emit initial function code
  o << "  const unsigned opcode = MI.getOpcode();\n"
    << "  unsigned Value = InstBits[opcode];\n"
    << "  unsigned op;\n"
    << "  switch (opcode) {\n";

  // Emit each case statement
  std::map<std::string, std::vector<std::string> >::iterator IE, EE;
  for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
    const std::string &Case = IE->first;
    std::vector<std::string> &InstList = IE->second;

    for (int i = 0, N = InstList.size(); i < N; i++) {
      if (i) o << "\n";
      o << "    case " << Namespace << InstList[i]  << ":";
    }
    o << " {\n";
    o << Case;
    o << "      break;\n"
      << "    }\n";
  }

  // Default case: unhandled opcode
  o << "  default:\n"
    << "    std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
    << "    abort();\n"
    << "  }\n"
    << "  return Value;\n"
    << "}\n\n";
}
<|endoftext|>


<commit_before>//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//

#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "Support/Debug.h"
using namespace llvm;

void CodeEmitterGen::run(std::ostream &o) {
  CodeGenTarget Target;
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  EmitSourceFileHeader("Machine Code Emitter", o);

  std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";

  //const std::string &Namespace = Inst->getValue("Namespace")->getName();
  o << "unsigned " << Target.getName() << "CodeEmitter::"
    << "getBinaryCodeForInstr(MachineInstr &MI) {\n"
    << "  unsigned Value = 0;\n"
    << "  DEBUG(std::cerr << MI);\n"
    << "  switch (MI.getOpcode()) {\n";
  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
       I != E; ++I) {
    Record *R = *I;
    o << "    case " << Namespace << R->getName() << ": {\n"
      << "      DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n";

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    unsigned Value = 0;
    const std::vector<RecordVal> &Vals = R->getValues();

    DEBUG(o << "      // prefilling: ");
    // Start by filling in fixed values...
    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
      if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
        Value |= B->getValue() << (e-i-1);
        DEBUG(o << B->getValue());
      } else {
        DEBUG(o << "0");
      }
    }
    DEBUG(o << "\n");

    DEBUG(o << "      // " << *R->getValue("Inst") << "\n");
    o << "      Value = " << Value << "U;\n\n";

    // Loop over all of the fields in the instruction determining which are the
    // operands to the instruction.
    //
    unsigned op = 0;
    std::map<std::string, unsigned> OpOrder;
    std::map<std::string, bool> OpContinuous;
    for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
      if (!Vals[i].getPrefix() &&  !Vals[i].getValue()->isComplete()) {
        // Is the operand continuous? If so, we can just mask and OR it in
        // instead of doing it bit-by-bit, saving a lot in runtime cost.
        const BitsInit *InstInit = BI;
        int beginBitInVar = -1, endBitInVar = -1;
        int beginBitInInst = -1, endBitInInst = -1;
        bool continuous = true;

        for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) {
          if (VarBitInit *VBI =
              dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) {
            TypedInit *TI = VBI->getVariable();
            if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
              // only process the current variable
              if (VI->getName() != Vals[i].getName())
                continue;

              if (beginBitInVar == -1)
                beginBitInVar = VBI->getBitNum();

              if (endBitInVar == -1)
                endBitInVar = VBI->getBitNum();
              else {
                if (endBitInVar == (int)VBI->getBitNum() + 1)
                  endBitInVar = VBI->getBitNum();
                else {
                  continuous = false;
                  break;
                }
              }

              if (beginBitInInst == -1)
                beginBitInInst = bit;
              if (endBitInInst == -1)
                endBitInInst = bit;
              else {
                if (endBitInInst == bit + 1)
                  endBitInInst = bit;
                else {
                  continuous = false;
                  break;
                }
              }

              // maintain same distance between bits in field and bits in
              // instruction. if the relative distances stay the same
              // throughout,
              if (beginBitInVar - (int)VBI->getBitNum() !=
                  beginBitInInst - bit) {
                continuous = false;
                break;
              }
            }
          }
        }

        // If we have found no bit in "Inst" which comes from this field, then
        // this is not an operand!!
        if (beginBitInInst != -1) {
          o << "      // op" << op << ": " << Vals[i].getName() << "\n"
            << "      int64_t op" << op
            <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n";
          //<< "   MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n";
          OpOrder[Vals[i].getName()] = op++;

          DEBUG(o << "      // Var: begin = " << beginBitInVar
                  << ", end = " << endBitInVar
                  << "; Inst: begin = " << beginBitInInst
                  << ", end = " << endBitInInst << "\n");

          if (continuous) {
            DEBUG(o << "      // continuous: op" << OpOrder[Vals[i].getName()]
                    << "\n");

            // Mask off the right bits
            // Low mask (ie. shift, if necessary)
            assert(endBitInVar >= 0 && "Negative shift amount in masking!");
            if (endBitInVar != 0) {
              o << "      op" << OpOrder[Vals[i].getName()]
                << " >>= " << endBitInVar << ";\n";
              beginBitInVar -= endBitInVar;
              endBitInVar = 0;
            }

            // High mask
            o << "      op" << OpOrder[Vals[i].getName()]
              << " &= (1<<" << beginBitInVar+1 << ") - 1;\n";

            // Shift the value to the correct place (according to place in inst)
            assert(endBitInInst >= 0 && "Negative shift amount!");
            if (endBitInInst != 0)
              o << "      op" << OpOrder[Vals[i].getName()]
              << " <<= " << endBitInInst << ";\n";

            // Just OR in the result
            o << "      Value |= op" << OpOrder[Vals[i].getName()] << ";\n";
          }

          // otherwise, will be taken care of in the loop below using this
          // value:
          OpContinuous[Vals[i].getName()] = continuous;
        }
      }
    }

    for (unsigned f = 0, e = Vals.size(); f != e; ++f) {
      if (Vals[f].getPrefix()) {
        BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();

        // Scan through the field looking for bit initializers of the current
        // variable...
        for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) {
          Init *I = FieldInitializer->getBit(i);
          if (BitInit *BI = dynamic_cast<BitInit*>(I)) {
            DEBUG(o << "      // bit init: f: " << f << ", i: " << i << "\n");
          } else if (UnsetInit *UI = dynamic_cast<UnsetInit*>(I)) {
            DEBUG(o << "      // unset init: f: " << f << ", i: " << i << "\n");
          } else if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(I)) {
            TypedInit *TI = VBI->getVariable();
            if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
              // If the bits of the field are laid out consecutively in the
              // instruction, then instead of separately ORing in bits, just
              // mask and shift the entire field for efficiency.
              if (OpContinuous[VI->getName()]) {
                // already taken care of in the loop above, thus there is no
                // need to individually OR in the bits

                // for debugging, output the regular version anyway, commented
                DEBUG(o << "      // Value |= getValueBit(op"
                        << OpOrder[VI->getName()] << ", " << VBI->getBitNum()
                        << ")" << " << " << i << ";\n");
              } else {
                o << "      Value |= getValueBit(op" << OpOrder[VI->getName()]
                  << ", " << VBI->getBitNum()
                  << ")" << " << " << i << ";\n";
              }
            } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
              // FIXME: implement this!
              o << "FIELD INIT not implemented yet!\n";
            } else {
              o << "Error: UNIMPLEMENTED\n";
            }
          }
        }
      }
    }

    o << "      break;\n"
      << "    }\n";
  }

  o << "  default:\n"
    << "    std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
    << "    abort();\n"
    << "  }\n"
    << "  return Value;\n"
    << "}\n";

  EmitSourceFileTail(o);
}
<commit_msg>Deleted commented-out code as we now get namespace directly, add comments<commit_after>//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//

#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "Support/Debug.h"
using namespace llvm;

void CodeEmitterGen::run(std::ostream &o) {
  CodeGenTarget Target;
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  EmitSourceFileHeader("Machine Code Emitter", o);
  std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";

  // Emit function declaration
  o << "unsigned " << Target.getName() << "CodeEmitter::"
    << "getBinaryCodeForInstr(MachineInstr &MI) {\n"
    << "  unsigned Value = 0;\n"
    << "  DEBUG(std::cerr << MI);\n"
    << "  switch (MI.getOpcode()) {\n";

  // Emit a case statement for each opcode
  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
       I != E; ++I) {
    Record *R = *I;
    o << "    case " << Namespace << R->getName() << ": {\n"
      << "      DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n";

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    unsigned Value = 0;
    const std::vector<RecordVal> &Vals = R->getValues();

    DEBUG(o << "      // prefilling: ");
    // Start by filling in fixed values...
    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
      if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
        Value |= B->getValue() << (e-i-1);
        DEBUG(o << B->getValue());
      } else {
        DEBUG(o << "0");
      }
    }
    DEBUG(o << "\n");

    DEBUG(o << "      // " << *R->getValue("Inst") << "\n");
    o << "      Value = " << Value << "U;\n\n";

    // Loop over all of the fields in the instruction determining which are the
    // operands to the instruction.
    //
    unsigned op = 0;
    std::map<std::string, unsigned> OpOrder;
    std::map<std::string, bool> OpContinuous;
    for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
      if (!Vals[i].getPrefix() &&  !Vals[i].getValue()->isComplete()) {
        // Is the operand continuous? If so, we can just mask and OR it in
        // instead of doing it bit-by-bit, saving a lot in runtime cost.
        const BitsInit *InstInit = BI;
        int beginBitInVar = -1, endBitInVar = -1;
        int beginBitInInst = -1, endBitInInst = -1;
        bool continuous = true;

        for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) {
          if (VarBitInit *VBI =
              dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) {
            TypedInit *TI = VBI->getVariable();
            if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
              // only process the current variable
              if (VI->getName() != Vals[i].getName())
                continue;

              if (beginBitInVar == -1)
                beginBitInVar = VBI->getBitNum();

              if (endBitInVar == -1)
                endBitInVar = VBI->getBitNum();
              else {
                if (endBitInVar == (int)VBI->getBitNum() + 1)
                  endBitInVar = VBI->getBitNum();
                else {
                  continuous = false;
                  break;
                }
              }

              if (beginBitInInst == -1)
                beginBitInInst = bit;
              if (endBitInInst == -1)
                endBitInInst = bit;
              else {
                if (endBitInInst == bit + 1)
                  endBitInInst = bit;
                else {
                  continuous = false;
                  break;
                }
              }

              // maintain same distance between bits in field and bits in
              // instruction. if the relative distances stay the same
              // throughout,
              if (beginBitInVar - (int)VBI->getBitNum() !=
                  beginBitInInst - bit) {
                continuous = false;
                break;
              }
            }
          }
        }

        // If we have found no bit in "Inst" which comes from this field, then
        // this is not an operand!!
        if (beginBitInInst != -1) {
          o << "      // op" << op << ": " << Vals[i].getName() << "\n"
            << "      int64_t op" << op
            <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n";
          //<< "   MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n";
          OpOrder[Vals[i].getName()] = op++;

          DEBUG(o << "      // Var: begin = " << beginBitInVar
                  << ", end = " << endBitInVar
                  << "; Inst: begin = " << beginBitInInst
                  << ", end = " << endBitInInst << "\n");

          if (continuous) {
            DEBUG(o << "      // continuous: op" << OpOrder[Vals[i].getName()]
                    << "\n");

            // Mask off the right bits
            // Low mask (ie. shift, if necessary)
            assert(endBitInVar >= 0 && "Negative shift amount in masking!");
            if (endBitInVar != 0) {
              o << "      op" << OpOrder[Vals[i].getName()]
                << " >>= " << endBitInVar << ";\n";
              beginBitInVar -= endBitInVar;
              endBitInVar = 0;
            }

            // High mask
            o << "      op" << OpOrder[Vals[i].getName()]
              << " &= (1<<" << beginBitInVar+1 << ") - 1;\n";

            // Shift the value to the correct place (according to place in inst)
            assert(endBitInInst >= 0 && "Negative shift amount!");
            if (endBitInInst != 0)
              o << "      op" << OpOrder[Vals[i].getName()]
              << " <<= " << endBitInInst << ";\n";

            // Just OR in the result
            o << "      Value |= op" << OpOrder[Vals[i].getName()] << ";\n";
          }

          // otherwise, will be taken care of in the loop below using this
          // value:
          OpContinuous[Vals[i].getName()] = continuous;
        }
      }
    }

    for (unsigned f = 0, e = Vals.size(); f != e; ++f) {
      if (Vals[f].getPrefix()) {
        BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();

        // Scan through the field looking for bit initializers of the current
        // variable...
        for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) {
          Init *I = FieldInitializer->getBit(i);
          if (BitInit *BI = dynamic_cast<BitInit*>(I)) {
            DEBUG(o << "      // bit init: f: " << f << ", i: " << i << "\n");
          } else if (UnsetInit *UI = dynamic_cast<UnsetInit*>(I)) {
            DEBUG(o << "      // unset init: f: " << f << ", i: " << i << "\n");
          } else if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(I)) {
            TypedInit *TI = VBI->getVariable();
            if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
              // If the bits of the field are laid out consecutively in the
              // instruction, then instead of separately ORing in bits, just
              // mask and shift the entire field for efficiency.
              if (OpContinuous[VI->getName()]) {
                // already taken care of in the loop above, thus there is no
                // need to individually OR in the bits

                // for debugging, output the regular version anyway, commented
                DEBUG(o << "      // Value |= getValueBit(op"
                        << OpOrder[VI->getName()] << ", " << VBI->getBitNum()
                        << ")" << " << " << i << ";\n");
              } else {
                o << "      Value |= getValueBit(op" << OpOrder[VI->getName()]
                  << ", " << VBI->getBitNum()
                  << ")" << " << " << i << ";\n";
              }
            } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
              // FIXME: implement this!
              o << "FIELD INIT not implemented yet!\n";
            } else {
              o << "Error: UNIMPLEMENTED\n";
            }
          }
        }
      }
    }

    o << "      break;\n"
      << "    }\n";
  }

  o << "  default:\n"
    << "    std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
    << "    abort();\n"
    << "  }\n"
    << "  return Value;\n"
    << "}\n";

  EmitSourceFileTail(o);
}
<|endoftext|>


<commit_before>#pragma once
#include "SolverProcess.hpp"
#include <metaSMT/support/parser/SMT2Parser.hpp>
#include <metaSMT/support/parser/UTreeEvaluator.hpp>
#include <metaSMT/support/parser/UTreeToString.hpp>
#include <metaSMT/support/SimpleSymbolTable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
#include <sstream>
#include <string>

namespace eval = metaSMT::evaluator;
namespace spirit = boost::spirit;

template < typename Context >
class Solver : public SolverBase {
public:
  typedef typename eval::UTreeEvaluator<Context> Evaluator;
  typedef metaSMT::type::TypedSymbol<Context> TypedSymbol;
  typedef boost::shared_ptr<TypedSymbol> TypedSymbolPtr;
  typedef std::map<std::string, TypedSymbolPtr> VarMap;

  typedef typename eval::SMT_Command_Map<Context>::Command Command;

public:
  Solver()
    : evaluator(solver, var_map)
    , parser(evaluator)
  {}

  void start() {
    std::cerr << "START" << '\n';
    for (;;) {
      std::string ret = SolverBase::success;
      std::string s = sp->child_read_command();
      // std::cerr << "[SOLVER] " << s << '\n';

      try {
        spirit::utree::list_type const list = parse(s);

        for ( spirit::utree::const_iterator it = list.begin(), ie = list.end();
                it != ie; ++it ) {
          spirit::utree const ast = *it;
          assert( ast.size() > 0 );

          std::string const command = eval::utreeToString(*ast.begin());
          // std::cerr << "COMMAND: " << command << '\n';

          boost::optional<Command> cmd =
          eval::SMT_Command_Map<Context>::get_command(command, solver, var_map, table);
          if ( !cmd )
            throw std::invalid_argument( "Unsupported command" );
          boost::optional<boost::any> result =
          eval::SMT_Command_Map<Context>::execute_command(*cmd, ast);
          if ( result ) {
            ret = makeResultString(command, *result);
          }
        }
      } catch (std::invalid_argument e) {
        std::cerr << "[SOLVER] " << e.what() << std::endl;
        ret = e.what();
      }
      // std::cerr << "[SOLVER] CHILD WRITE COMMAND: " << ret << '\n';
      sp->child_write_command(ret);
    }
  }

private:
  spirit::utree::list_type parse(std::string const &s) {
    std::stringstream ss(s);
    spirit::utree::list_type list;
    bool const success = parser.parse(ss, list);
    // std::cerr << "[SOLVER] SUCCESS = " << success << '\n';
    if ( !success )
      throw std::invalid_argument( "Unsupported syntax" );
    return list;
  }

  std::string makeCheckSatResult(boost::any const &result) {
    bool const sat = boost::any_cast<bool>(result);
    std::cerr << "[SOLVER] check-sat = " << sat << '\n';
    return (sat ? "sat" : "unsat");
  }

  std::string makeGetValueResult(boost::any const &result) {
    typedef boost::tuple<std::string,TypedSymbolPtr> var_type;
    var_type var = boost::any_cast<var_type>(result);
    std::string const name = boost::get<0>(var);
    TypedSymbolPtr const symbol = boost::get<1>(var);
    std::string ret = "<Unknown>";
    if ( symbol->isBool() ) {
      bool const b = read_value(solver, symbol->eval(solver));
      ret = "((" + name + " " + (b ? "true" : "false") + "))";
    }
    else if (symbol->isBitVector() ) {
      std::string const value = read_value(solver, symbol->eval(solver));
      ret = "((" + name + " #b" + value + "))";
    }
    else {
      assert( false && "Variable type is not supported" );
    }
    std::cerr << "[SOLVER] get-value = " << ret << '\n';
    return ret;
  }

  std::string makeResultString(std::string const &name,
                               boost::any const &result) {
    if ( name == "check-sat" ) {
      return makeCheckSatResult(result);
    }
    else if ( name == "get-value" ) {
      return makeGetValueResult(result);
    }
    assert( false && "Command has no result" );
    return "<Unknown>";
  }

private:
  Context solver;
  VarMap var_map;
  Evaluator evaluator;
  metaSMT::smt2::SMT2Parser<Evaluator> parser;
  metaSMT::support::simple_symbol_table table;
}; // Solver
<commit_msg>fixes possible call to pthread_kill on negative ids (which may lead to killing the xserver and other applications)<commit_after>#pragma once
#include "SolverProcess.hpp"
#include <metaSMT/support/parser/SMT2Parser.hpp>
#include <metaSMT/support/parser/UTreeEvaluator.hpp>
#include <metaSMT/support/parser/UTreeToString.hpp>
#include <metaSMT/support/SimpleSymbolTable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
#include <sstream>
#include <string>

namespace eval = metaSMT::evaluator;
namespace spirit = boost::spirit;

template < typename Context >
class Solver : public SolverBase {
public:
  typedef typename eval::UTreeEvaluator<Context> Evaluator;
  typedef metaSMT::type::TypedSymbol<Context> TypedSymbol;
  typedef boost::shared_ptr<TypedSymbol> TypedSymbolPtr;
  typedef std::map<std::string, TypedSymbolPtr> VarMap;

  typedef typename eval::SMT_Command_Map<Context>::Command Command;

public:
  Solver()
    : evaluator(solver, var_map)
    , parser(evaluator)
  {}

  void start() {
    std::cerr << "START" << '\n';
    for (;;) {
      std::string ret = SolverBase::success;
      std::string s = sp->child_read_command();
      // std::cerr << "[SOLVER] " << s << '\n';

      try {
        spirit::utree::list_type const list = parse(s);

        for ( spirit::utree::const_iterator it = list.begin(), ie = list.end();
                it != ie; ++it ) {
          spirit::utree const ast = *it;
          assert( ast.size() > 0 );

          std::string const command = eval::utreeToString(*ast.begin());
          // std::cerr << "COMMAND: " << command << '\n';

          boost::optional<Command> cmd =
          eval::SMT_Command_Map<Context>::get_command(command, solver, var_map, table);
          if ( !cmd )
            throw std::invalid_argument( "Unsupported command" );
          boost::optional<boost::any> result =
          eval::SMT_Command_Map<Context>::execute_command(*cmd, ast);
          if ( result ) {
            ret = makeResultString(command, *result);
          }
        }
      } catch (std::exception e) {
        std::cerr << "[SOLVER] " << e.what() << std::endl;
        ret = "error";
      }
      // std::cerr << "[SOLVER] CHILD WRITE COMMAND: " << ret << '\n';
      sp->child_write_command(ret);
    }
  }

private:
  spirit::utree::list_type parse(std::string const &s) {
    std::stringstream ss(s);
    spirit::utree::list_type list;
    bool const success = parser.parse(ss, list);
    // std::cerr << "[SOLVER] SUCCESS = " << success << '\n';
    if ( !success )
      throw std::invalid_argument( "Unsupported syntax" );
    return list;
  }

  std::string makeCheckSatResult(boost::any const &result) {
    bool const sat = boost::any_cast<bool>(result);
    std::cerr << "[SOLVER] check-sat = " << sat << '\n';
    return (sat ? "sat" : "unsat");
  }

  std::string makeGetValueResult(boost::any const &result) {
    typedef boost::tuple<std::string,TypedSymbolPtr> var_type;
    var_type var = boost::any_cast<var_type>(result);
    std::string const name = boost::get<0>(var);
    TypedSymbolPtr const symbol = boost::get<1>(var);
    std::string ret = "<Unknown>";
    if ( symbol->isBool() ) {
      bool const b = read_value(solver, symbol->eval(solver));
      ret = "((" + name + " " + (b ? "true" : "false") + "))";
    }
    else if (symbol->isBitVector() ) {
      std::string const value = read_value(solver, symbol->eval(solver));
      ret = "((" + name + " #b" + value + "))";
    }
    else {
      assert( false && "Variable type is not supported" );
    }
    std::cerr << "[SOLVER] get-value = " << ret << '\n';
    return ret;
  }

  std::string makeResultString(std::string const &name,
                               boost::any const &result) {
    if ( name == "check-sat" ) {
      return makeCheckSatResult(result);
    }
    else if ( name == "get-value" ) {
      return makeGetValueResult(result);
    }
    assert( false && "Command has no result" );
    return "<Unknown>";
  }

private:
  Context solver;
  VarMap var_map;
  Evaluator evaluator;
  metaSMT::smt2::SMT2Parser<Evaluator> parser;
  metaSMT::support::simple_symbol_table table;
}; // Solver
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2007 Gunnar Raetsch
 * Copyright (C) 1999-2007 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include "lib/config.h"

#include <stdio.h>
#include <string.h>

#include "lib/io.h"

#include "structure/PlifArray.h"
#include "structure/Plif.h"

#define PLIFARRAY_DEBUG

CPlifArray::CPlifArray()
{
	min_value = -1e6 ;
	max_value = 1e6 ;
}

CPlifArray::~CPlifArray()
{
}

void CPlifArray::add_plif(CPlifBase* new_plif)
{
	ASSERT(new_plif!=NULL) ;
	m_array.append_element(new_plif) ;

	min_value = -1e6 ;
	for (INT i=0; i<m_array.get_num_elements(); i++)
	{
		ASSERT(m_array[i]!=NULL)
		if (!m_array[i]->uses_svm_values())
			min_value = CMath::max(min_value, m_array[i]->get_min_value()) ;
	}

	max_value = 1e6 ;
	for (INT i=0; i<m_array.get_num_elements(); i++)
		if (!m_array[i]->uses_svm_values())
			max_value = CMath::min(max_value, m_array[i]->get_max_value()) ;
}

void CPlifArray::clear()
{
	m_array.clear_array();
	min_value = -1e6 ;
	max_value = 1e6 ;
}

DREAL CPlifArray::lookup_penalty(DREAL p_value, DREAL* svm_values) const
{
	if (p_value<min_value || p_value>max_value)
		return -CMath::INFTY ;

	DREAL ret = 0.0 ;
	for (INT i=0; i<m_array.get_num_elements(); i++)
		ret += m_array[i]->lookup_penalty(p_value, svm_values) ;
	return ret ;
}

DREAL CPlifArray::lookup_penalty(INT p_value, DREAL* svm_values) const
{
	if (p_value<min_value || p_value>max_value)
		return -CMath::INFTY ;

	DREAL ret = 0.0 ;
	for (INT i=0; i<m_array.get_num_elements(); i++)
	{
		DREAL val = m_array[i]->lookup_penalty(p_value, svm_values) ;
		ret += val ;
#ifdef PLIFARRAY_DEBUG
		CPlif * plif = (CPlif*)m_array[i] ;
		if (plif->get_use_svm())
			SG_DEBUG( "penalty[%i]=%1.2f (use_svm=%i -> %1.2f)\n", i, val, plif->get_use_svm(), svm_values[plif->get_use_svm()-1]) ;
		else
		SG_DEBUG( "penalty[%i]=%1.2f\n", i, val) ;
#endif
	}
	return ret ;
}

void CPlifArray::penalty_clear_derivative()
{
	for (INT i=0; i<m_array.get_num_elements(); i++)
		m_array[i]->penalty_clear_derivative() ;
}

void CPlifArray::penalty_add_derivative(DREAL p_value, DREAL* svm_values)
{
	for (INT i=0; i<m_array.get_num_elements(); i++)
		m_array[i]->penalty_add_derivative(p_value, svm_values) ;
}

bool CPlifArray::uses_svm_values() const
{
	for (INT i=0; i<m_array.get_num_elements(); i++)
		if (m_array[i]->uses_svm_values())
			return true ;
	return false ;
}

INT CPlifArray::get_max_id() const
{
	INT max_id = 0 ;
	for (INT i=0; i<m_array.get_num_elements(); i++)
		max_id = CMath::max(max_id, m_array[i]->get_max_id()) ;
	return max_id ;
}

<commit_msg>more debug stuff ... (sorry for the spam).<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2007 Gunnar Raetsch
 * Copyright (C) 1999-2007 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include "lib/config.h"

#include <stdio.h>
#include <string.h>

#include "lib/io.h"

#include "structure/PlifArray.h"
#include "structure/Plif.h"

#define PLIFARRAY_DEBUG

CPlifArray::CPlifArray()
{
	min_value = -1e6 ;
	max_value = 1e6 ;
}

CPlifArray::~CPlifArray()
{
}

void CPlifArray::add_plif(CPlifBase* new_plif)
{
	ASSERT(new_plif!=NULL) ;
	m_array.append_element(new_plif) ;

	min_value = -1e6 ;
	for (INT i=0; i<m_array.get_num_elements(); i++)
	{
		ASSERT(m_array[i]!=NULL)
		if (!m_array[i]->uses_svm_values())
			min_value = CMath::max(min_value, m_array[i]->get_min_value()) ;
	}

	max_value = 1e6 ;
	for (INT i=0; i<m_array.get_num_elements(); i++)
		if (!m_array[i]->uses_svm_values())
			max_value = CMath::min(max_value, m_array[i]->get_max_value()) ;
}

void CPlifArray::clear()
{
	m_array.clear_array();
	min_value = -1e6 ;
	max_value = 1e6 ;
}

DREAL CPlifArray::lookup_penalty(DREAL p_value, DREAL* svm_values) const
{
	if (p_value<min_value || p_value>max_value)
		return -CMath::INFTY ;

	DREAL ret = 0.0 ;
	for (INT i=0; i<m_array.get_num_elements(); i++)
		ret += m_array[i]->lookup_penalty(p_value, svm_values) ;
	return ret ;
}

DREAL CPlifArray::lookup_penalty(INT p_value, DREAL* svm_values) const
{
	if (p_value<min_value || p_value>max_value)
		return -CMath::INFTY ;

	DREAL ret = 0.0 ;
	for (INT i=0; i<m_array.get_num_elements(); i++)
	{
		DREAL val = m_array[i]->lookup_penalty(p_value, svm_values) ;
		ret += val ;
#ifdef PLIFARRAY_DEBUG
		CPlif * plif = (CPlif*)m_array[i] ;
		if (plif->get_use_svm())
			fprintf(stderr, "penalty[%i]=%1.5f (use_svm=%i -> %1.5f)\n", i, val, plif->get_use_svm(), svm_values[plif->get_use_svm()-1]) ;
		else
			fprintf(stderr, "penalty[%i]=%1.5f\n", i, val) ;
#endif
	}
	return ret ;
}

void CPlifArray::penalty_clear_derivative()
{
	for (INT i=0; i<m_array.get_num_elements(); i++)
		m_array[i]->penalty_clear_derivative() ;
}

void CPlifArray::penalty_add_derivative(DREAL p_value, DREAL* svm_values)
{
	for (INT i=0; i<m_array.get_num_elements(); i++)
		m_array[i]->penalty_add_derivative(p_value, svm_values) ;
}

bool CPlifArray::uses_svm_values() const
{
	for (INT i=0; i<m_array.get_num_elements(); i++)
		if (m_array[i]->uses_svm_values())
			return true ;
	return false ;
}

INT CPlifArray::get_max_id() const
{
	INT max_id = 0 ;
	for (INT i=0; i<m_array.get_num_elements(); i++)
		max_id = CMath::max(max_id, m_array[i]->get_max_id()) ;
	return max_id ;
}

<|endoftext|>


<commit_before>/***************************************************************************
 *            stack_benchmark.cpp
 *
 *  Wed Jul 12 18:28:43 2006
 *  Copyright  2006  User Roman Dementiev
 *  Email
 ****************************************************************************/

#include "stxxl.h"

#define MEM_2_RESERVE    (768 * 1024 * 1024)

#ifndef BLOCK_SIZE
 #define    BLOCK_SIZE (2 * 1024 * 1024)
#endif

#ifndef DISKS
 #define DISKS 4
#endif

template <unsigned RECORD_SIZE>
struct my_record_
{
    char data[RECORD_SIZE];
    my_record_() { }
};

template <unsigned RECORD_SIZE>
inline std::ostream & operator << (std::ostream & o, const my_record_<RECORD_SIZE> &)
{
    o << ".";
    return o;
}

template <class my_record>
void run_stxxl_growshrink2_stack(stxxl::int64 volume)
{
    typedef typename stxxl::STACK_GENERATOR<my_record, stxxl::external,
                                            stxxl::grow_shrink2, DISKS, BLOCK_SIZE>::result stack_type;
    typedef typename stack_type::block_type block_type;

    STXXL_MSG("Record size: " << sizeof(my_record) << " bytes");

    stxxl::prefetch_pool<block_type> p_pool(DISKS * 4);
    stxxl::write_pool<block_type>    w_pool(DISKS * 4);

    stack_type Stack(p_pool, w_pool);

    stxxl::int64 ops = volume / sizeof(my_record);

    stxxl::int64 i;

    my_record cur;

    stxxl::stats * Stats = stxxl::stats::get_instance();
    Stats->reset();

    stxxl::timer Timer;
    Timer.start();

    for (i = 0; i < ops; ++i)
    {
        Stack.push(cur);
    }

    Timer.stop();

    STXXL_MSG("Records in Stack: " << Stack.size());
    if (i != Stack.size())
    {
        STXXL_MSG("Size does not match");
        abort();
    }

    STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) <<
              " seconds : " << (double (volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) <<
              " MB/s");

    std::cout << *Stats;
    Stats->reset();

    Stack.set_prefetch_aggr(DISKS * 8);

    ////////////////////////////////////////////////
    Timer.reset();
    Timer.start();

    for (i = 0; i < ops; ++i)
    {
        Stack.pop();
    }

    Timer.stop();

    STXXL_MSG("Records in Stack: " << Stack.size());
    if (!Stack.empty())
    {
        STXXL_MSG("Stack must be empty");
        abort();
    }

    STXXL_MSG("Deletions elapsed time: " << (Timer.mseconds() / 1000.) <<
              " seconds : " << (double (volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) <<
              " MB/s");

    std::cout << *Stats;
}

template <class my_record>
void run_stxxl_normal_stack(stxxl::int64 volume)
{
    typedef typename stxxl::STACK_GENERATOR<my_record, stxxl::external,
                                            stxxl::normal, DISKS, BLOCK_SIZE>::result stack_type;
    typedef typename stack_type::block_type block_type;

    STXXL_MSG("Record size: " << sizeof(my_record) << " bytes");

    stack_type Stack;

    stxxl::int64 ops = volume / sizeof(my_record);

    stxxl::int64 i;

    my_record cur;

    stxxl::stats * Stats = stxxl::stats::get_instance();
    Stats->reset();

    stxxl::timer Timer;
    Timer.start();

    for (i = 0; i < ops; ++i)
    {
        Stack.push(cur);
    }

    Timer.stop();

    STXXL_MSG("Records in Stack: " << Stack.size());
    if (i != Stack.size())
    {
        STXXL_MSG("Size does not match");
        abort();
    }

    STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) <<
              " seconds : " << (double (volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) <<
              " MB/s");

    std::cout << *Stats;
    Stats->reset();

    ////////////////////////////////////////////////
    Timer.reset();
    Timer.start();

    for (i = 0; i < ops; ++i)
    {
        Stack.pop();
    }

    Timer.stop();

    STXXL_MSG("Records in Stack: " << Stack.size());
    if (!Stack.empty())
    {
        STXXL_MSG("Stack must be empty");
        abort();
    }

    STXXL_MSG("Deletions elapsed time: " << (Timer.mseconds() / 1000.) <<
              " seconds : " << (double (volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) <<
              " MB/s");

    std::cout << *Stats;
}

int main(int argc, char * argv[])
{
    STXXL_MSG("stxxl::pq block size: " << BLOCK_SIZE << " bytes");

#ifdef STXXL_DIRECT_IO_OFF
    STXXL_MSG("STXXL_DIRECT_IO_OFF is defined");
#else
    STXXL_MSG("STXXL_DIRECT_IO_OFF is NOT defined");
#endif

    if (argc < 3)
    {
        STXXL_MSG("Usage: " << argv[0] << " version #volume");
        STXXL_MSG("\t version = 1: grow-shrink-stack2 with 4 byte records");
        STXXL_MSG("\t version = 2: grow-shrink-stack2 with 32 byte records");
        STXXL_MSG("\t version = 3: normal-stack with 4 byte records");
        STXXL_MSG("\t version = 4: normal-stack with 32 byte records");
        return 0;
    }

    int version = atoi(argv[1]);
    stxxl::int64 volume = atoll(argv[2]);

    STXXL_MSG("Allocating array with size " << MEM_2_RESERVE
                                            << " bytes to prevent file buffering.");
    int * array = new int[MEM_2_RESERVE / sizeof(int)];
    std::fill(array, array + (MEM_2_RESERVE / sizeof(int)), 0);

    STXXL_MSG("Running version: " << version);
    STXXL_MSG("Data volume    : " << volume << " bytes");

    switch (version)
    {
    case 1:
        run_stxxl_growshrink2_stack < my_record_ < 4 > > (volume);
        break;
    case 2:
        run_stxxl_growshrink2_stack < my_record_ < 32 > > (volume);
        break;
    case 3:
        run_stxxl_normal_stack < my_record_ < 4 > > (volume);
        break;
    case 4:
        run_stxxl_normal_stack < my_record_ < 32 > > (volume);
        break;
    default:
        STXXL_MSG("Unsupported version " << version);
    }

    delete [] array;
}
<commit_msg>initialize unused data to avoid warning when copying<commit_after>/***************************************************************************
 *            stack_benchmark.cpp
 *
 *  Wed Jul 12 18:28:43 2006
 *  Copyright  2006  User Roman Dementiev
 *  Email
 ****************************************************************************/

#include "stxxl.h"

#define MEM_2_RESERVE    (768 * 1024 * 1024)

#ifndef BLOCK_SIZE
 #define    BLOCK_SIZE (2 * 1024 * 1024)
#endif

#ifndef DISKS
 #define DISKS 4
#endif

template <unsigned RECORD_SIZE>
struct my_record_
{
    char data[RECORD_SIZE];
    my_record_()
    {
        bzero(data, sizeof(data));
    }
};

template <unsigned RECORD_SIZE>
inline std::ostream & operator << (std::ostream & o, const my_record_<RECORD_SIZE> &)
{
    o << ".";
    return o;
}

template <class my_record>
void run_stxxl_growshrink2_stack(stxxl::int64 volume)
{
    typedef typename stxxl::STACK_GENERATOR<my_record, stxxl::external,
                                            stxxl::grow_shrink2, DISKS, BLOCK_SIZE>::result stack_type;
    typedef typename stack_type::block_type block_type;

    STXXL_MSG("Record size: " << sizeof(my_record) << " bytes");

    stxxl::prefetch_pool<block_type> p_pool(DISKS * 4);
    stxxl::write_pool<block_type>    w_pool(DISKS * 4);

    stack_type Stack(p_pool, w_pool);

    stxxl::int64 ops = volume / sizeof(my_record);

    stxxl::int64 i;

    my_record cur;

    stxxl::stats * Stats = stxxl::stats::get_instance();
    Stats->reset();

    stxxl::timer Timer;
    Timer.start();

    for (i = 0; i < ops; ++i)
    {
        Stack.push(cur);
    }

    Timer.stop();

    STXXL_MSG("Records in Stack: " << Stack.size());
    if (i != Stack.size())
    {
        STXXL_MSG("Size does not match");
        abort();
    }

    STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) <<
              " seconds : " << (double (volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) <<
              " MB/s");

    std::cout << *Stats;
    Stats->reset();

    Stack.set_prefetch_aggr(DISKS * 8);

    ////////////////////////////////////////////////
    Timer.reset();
    Timer.start();

    for (i = 0; i < ops; ++i)
    {
        Stack.pop();
    }

    Timer.stop();

    STXXL_MSG("Records in Stack: " << Stack.size());
    if (!Stack.empty())
    {
        STXXL_MSG("Stack must be empty");
        abort();
    }

    STXXL_MSG("Deletions elapsed time: " << (Timer.mseconds() / 1000.) <<
              " seconds : " << (double (volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) <<
              " MB/s");

    std::cout << *Stats;
}

template <class my_record>
void run_stxxl_normal_stack(stxxl::int64 volume)
{
    typedef typename stxxl::STACK_GENERATOR<my_record, stxxl::external,
                                            stxxl::normal, DISKS, BLOCK_SIZE>::result stack_type;
    typedef typename stack_type::block_type block_type;

    STXXL_MSG("Record size: " << sizeof(my_record) << " bytes");

    stack_type Stack;

    stxxl::int64 ops = volume / sizeof(my_record);

    stxxl::int64 i;

    my_record cur;

    stxxl::stats * Stats = stxxl::stats::get_instance();
    Stats->reset();

    stxxl::timer Timer;
    Timer.start();

    for (i = 0; i < ops; ++i)
    {
        Stack.push(cur);
    }

    Timer.stop();

    STXXL_MSG("Records in Stack: " << Stack.size());
    if (i != Stack.size())
    {
        STXXL_MSG("Size does not match");
        abort();
    }

    STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) <<
              " seconds : " << (double (volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) <<
              " MB/s");

    std::cout << *Stats;
    Stats->reset();

    ////////////////////////////////////////////////
    Timer.reset();
    Timer.start();

    for (i = 0; i < ops; ++i)
    {
        Stack.pop();
    }

    Timer.stop();

    STXXL_MSG("Records in Stack: " << Stack.size());
    if (!Stack.empty())
    {
        STXXL_MSG("Stack must be empty");
        abort();
    }

    STXXL_MSG("Deletions elapsed time: " << (Timer.mseconds() / 1000.) <<
              " seconds : " << (double (volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) <<
              " MB/s");

    std::cout << *Stats;
}

int main(int argc, char * argv[])
{
    STXXL_MSG("stxxl::pq block size: " << BLOCK_SIZE << " bytes");

#ifdef STXXL_DIRECT_IO_OFF
    STXXL_MSG("STXXL_DIRECT_IO_OFF is defined");
#else
    STXXL_MSG("STXXL_DIRECT_IO_OFF is NOT defined");
#endif

    if (argc < 3)
    {
        STXXL_MSG("Usage: " << argv[0] << " version #volume");
        STXXL_MSG("\t version = 1: grow-shrink-stack2 with 4 byte records");
        STXXL_MSG("\t version = 2: grow-shrink-stack2 with 32 byte records");
        STXXL_MSG("\t version = 3: normal-stack with 4 byte records");
        STXXL_MSG("\t version = 4: normal-stack with 32 byte records");
        return 0;
    }

    int version = atoi(argv[1]);
    stxxl::int64 volume = atoll(argv[2]);

    STXXL_MSG("Allocating array with size " << MEM_2_RESERVE
                                            << " bytes to prevent file buffering.");
    int * array = new int[MEM_2_RESERVE / sizeof(int)];
    std::fill(array, array + (MEM_2_RESERVE / sizeof(int)), 0);

    STXXL_MSG("Running version: " << version);
    STXXL_MSG("Data volume    : " << volume << " bytes");

    switch (version)
    {
    case 1:
        run_stxxl_growshrink2_stack < my_record_ < 4 > > (volume);
        break;
    case 2:
        run_stxxl_growshrink2_stack < my_record_ < 32 > > (volume);
        break;
    case 3:
        run_stxxl_normal_stack < my_record_ < 4 > > (volume);
        break;
    case 4:
        run_stxxl_normal_stack < my_record_ < 32 > > (volume);
        break;
    default:
        STXXL_MSG("Unsupported version " << version);
    }

    delete [] array;
}
<|endoftext|>


<commit_before><commit_msg>Create tinyunzip.cc<commit_after><|endoftext|>


<commit_before>#include "QCodeEditor.h"

#include <QTextStream>
#include <QMessageBox>
#include <QFileDialog>
#include <QBoxLayout>
#include <QPainter>

#include "xo/system/system_tools.h"
#include "xo/system/assert.h"
#include "xo/string/string_tools.h"
#include "xo/system/log.h"
#include "xo/serialization/serialize.h"
#include "xo/numerical/math.h"
#include "xo/container/prop_node.h"
#include "QInputDialog"
#include "qt_convert.h"

QCodeEditor::QCodeEditor( QWidget* parent ) :
QPlainTextEdit( parent )
{
	QVBoxLayout* verticalLayout = new QVBoxLayout( this );
	verticalLayout->setContentsMargins( 0, 0, 0, 0 );
	setLayout( verticalLayout );

	QFont font;
	font.setFamily( QStringLiteral( "Consolas" ) );
	font.setPointSize( 9 );
	setFont( font );
	setLineWrapMode( QPlainTextEdit::NoWrap );
	setTabStopWidth( 16 );
	setWordWrapMode( QTextOption::NoWrap );
	//verticalLayout->addWidget( textEdit );

	setFrameStyle( QFrame::NoFrame );
	lineNumberArea = new LineNumberArea( this );

	connect( this, SIGNAL( blockCountChanged( int ) ), this, SLOT( updateLineNumberAreaWidth( int ) ) );
	connect( this, SIGNAL( updateRequest( QRect, int ) ), this, SLOT( updateLineNumberArea( QRect, int ) ) );

	updateLineNumberAreaWidth( 0 );

}

QCodeEditor::~QCodeEditor()
{}

void QCodeEditor::open( const QString& filename )
{
	syntaxHighlighter = new QCodeHighlighter( document(), QCodeHighlighter::detectLanguage( filename ) );

	QFile f( filename );
	if ( f.open( QFile::ReadOnly | QFile::Text ) )
	{
		QTextStream str( &f );
		QString data = str.readAll();
		setPlainText( data );
		fileName = filename;
	}
	else xo_error( "Could not open " + filename.toStdString() );
}

void QCodeEditor::openDialog( const QString& folder, const QString& fileTypes )
{
	auto fn = QFileDialog::getOpenFileName( this, "Open File", folder, fileTypes );
	if ( !fn.isEmpty() )
		open( fn );
}

void QCodeEditor::save()
{
	QFile file( fileName );
	if ( !file.open( QIODevice::WriteOnly ) )
	{
		QMessageBox::critical( this, "Error writing file", "Could not open file " + fileName );
		return;
	}
	else
	{
		QTextStream stream( &file );
		stream << toPlainText();
		stream.flush();
		file.close();
		document()->setModified( false );
	}
}

void QCodeEditor::saveAs( const QString& fn )
{
	auto new_fmt = path_from_qt( fn ).extension_no_dot().str();
	auto old_fmt = path_from_qt( fileName ).extension_no_dot().str();
	if ( new_fmt != old_fmt )
	{
		std::stringstream stri( toPlainText().toStdString() );
		xo::prop_node pn;
		stri >> *xo::make_serializer( old_fmt, pn );

		std::stringstream stro;
		stro << *xo::make_serializer( new_fmt, pn );

		syntaxHighlighter = new QCodeHighlighter( document(), QCodeHighlighter::detectLanguage( fn ) );
		setPlainText( QString( stro.str().c_str() ) );
	}

	fileName = fn;
	save();
}

void QCodeEditor::findDialog()
{
	QString text = QInputDialog::getText( this, "Find Text", "Text to find:", QLineEdit::Normal, findText );
	if ( !text.isNull() )
	{
		findText = text;
		moveCursor( QTextCursor::Start );
		if ( !findNext() )
			QMessageBox::warning( this, "Could not find text", "Could not find '" + findText + "'" );
	}
}

bool QCodeEditor::findNext( bool backwards )
{
	auto cursor = document()->find( findText, textCursor(), backwards ? QTextDocument::FindBackward : QTextDocument::FindFlags() );
	if ( !cursor.isNull() )
		setTextCursor( cursor );
	return !cursor.isNull();
}

QString QCodeEditor::getTitle()
{
	return QFileInfo( fileName ).fileName() + ( document()->isModified() ? "*" : "" );
}

void QCodeEditor::lineNumberAreaPaintEvent( QPaintEvent *event )
{
	QPainter painter( lineNumberArea );
	QColor c = palette().color( QWidget::backgroundRole() );
	painter.fillRect( event->rect(), c );

	QTextBlock block = firstVisibleBlock();
	int blockNumber = block.blockNumber();
	int top = (int)blockBoundingGeometry( block ).translated( contentOffset() ).top();
	int bottom = top + (int)blockBoundingRect( block ).height();

	while ( block.isValid() && top <= event->rect().bottom() ) {
		if ( block.isVisible() && bottom >= event->rect().top() ) {
			QString number = QString::number( blockNumber + 1 );
			painter.setPen( Qt::gray );
			painter.drawText( 0, top, lineNumberArea->width() - 2, fontMetrics().height(),
				Qt::AlignRight, number );
		}

		block = block.next();
		top = bottom;
		bottom = top + (int)blockBoundingRect( block ).height();
		++blockNumber;
	}
}

int QCodeEditor::lineNumberAreaWidth()
{
	int digits = 1;
	int max = qMax( 1, blockCount() );
	while ( max >= 10 ) {
		max /= 10;
		++digits;
	}

	int space = 4 + fontMetrics().width( QLatin1Char( '9' ) ) * digits;

	return space;
}

void QCodeEditor::formatDocument()
{
	auto cursor = textCursor();
	cursor.beginEditBlock();
	cursor.movePosition( QTextCursor::Start );

	auto indents = 0;
	while ( !cursor.atEnd() )
	{
		QString line = cursor.block().text();

		// count current amount of tabs
		auto tab_count = 0;
		while ( tab_count < line.size() && line[ tab_count ] == '\t' )
			++tab_count;

		auto leading_whitespace = tab_count;
		while ( leading_whitespace < line.size() && line[ leading_whitespace ].isSpace() )
			++leading_whitespace;

		QChar first_char = tab_count < line.size() ? line[ tab_count ] : QChar();
		auto desired_tabs = xo::max( 0, indents - int( first_char == '}' || first_char == ']' ) );

		if ( leading_whitespace != desired_tabs )
		{
			cursor.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, leading_whitespace );
			cursor.removeSelectedText();
			cursor.insertText( QString().fill( '\t', desired_tabs ) );
		}

		// update indents
		indents += line.count( '{' ) + line.count( '[' ) - line.count( '}' ) - line.count( ']' );

		if ( !cursor.movePosition( QTextCursor::NextBlock ) )
			break; // prevent infinite loop if this fails
	}
	cursor.endEditBlock();
}

void QCodeEditor::updateLineNumberAreaWidth( int newBlockCount )
{
	setViewportMargins( lineNumberAreaWidth(), 0, 0, 0 );
}

void QCodeEditor::updateLineNumberArea( const QRect& rect, int dy )
{
	if ( dy )
		lineNumberArea->scroll( 0, dy );
	else
		lineNumberArea->update( 0, rect.y(), lineNumberArea->width(), rect.height() );

	if ( rect.contains( viewport()->rect() ) )
		updateLineNumberAreaWidth( 0 );
}

void QCodeEditor::resizeEvent( QResizeEvent *event )
{
	QRect cr = contentsRect();
	if ( cr != previousRect ) // this is a hack to prevent a Qt bug causing infinite QResizeEvents
	{
		previousRect = cr;
		QPlainTextEdit::resizeEvent( event );
		lineNumberArea->setGeometry( QRect( cr.left(), cr.top(), lineNumberAreaWidth(), cr.height() ) );
	}
}

void QCodeEditor::keyPressEvent( QKeyEvent *e )
{
	QPlainTextEdit::keyPressEvent( e );

	switch ( language() )
	{
	case QCodeHighlighter::Language::zml:
		if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter || e->key() == '{' || e->key() == '}' )
			formatDocument();
	default:
		break;
	}
}
<commit_msg>U: more F5 key logic updates and fixes<commit_after>#include "QCodeEditor.h"

#include <QTextStream>
#include <QMessageBox>
#include <QFileDialog>
#include <QBoxLayout>
#include <QPainter>

#include "xo/system/system_tools.h"
#include "xo/system/assert.h"
#include "xo/string/string_tools.h"
#include "xo/system/log.h"
#include "xo/serialization/serialize.h"
#include "xo/numerical/math.h"
#include "xo/container/prop_node.h"
#include "QInputDialog"
#include "qt_convert.h"

QCodeEditor::QCodeEditor( QWidget* parent ) :
QPlainTextEdit( parent )
{
	QVBoxLayout* verticalLayout = new QVBoxLayout( this );
	verticalLayout->setContentsMargins( 0, 0, 0, 0 );
	setLayout( verticalLayout );

	QFont font;
	font.setFamily( QStringLiteral( "Consolas" ) );
	font.setPointSize( 9 );
	setFont( font );
	setLineWrapMode( QPlainTextEdit::NoWrap );
	setTabStopWidth( 16 );
	setWordWrapMode( QTextOption::NoWrap );
	//verticalLayout->addWidget( textEdit );

	setFrameStyle( QFrame::NoFrame );
	lineNumberArea = new LineNumberArea( this );

	connect( this, SIGNAL( blockCountChanged( int ) ), this, SLOT( updateLineNumberAreaWidth( int ) ) );
	connect( this, SIGNAL( updateRequest( QRect, int ) ), this, SLOT( updateLineNumberArea( QRect, int ) ) );

	updateLineNumberAreaWidth( 0 );
}

QCodeEditor::~QCodeEditor()
{}

void QCodeEditor::open( const QString& filename )
{
	syntaxHighlighter = new QCodeHighlighter( document(), QCodeHighlighter::detectLanguage( filename ) );

	QFile f( filename );
	if ( f.open( QFile::ReadOnly | QFile::Text ) )
	{
		QTextStream str( &f );
		QString data = str.readAll();
		setPlainText( data );
		fileName = filename;
	}
	else xo_error( "Could not open " + filename.toStdString() );
}

void QCodeEditor::openDialog( const QString& folder, const QString& fileTypes )
{
	auto fn = QFileDialog::getOpenFileName( this, "Open File", folder, fileTypes );
	if ( !fn.isEmpty() )
		open( fn );
}

void QCodeEditor::save()
{
	QFile file( fileName );
	if ( !file.open( QIODevice::WriteOnly ) )
	{
		QMessageBox::critical( this, "Error writing file", "Could not open file " + fileName );
		return;
	}
	else
	{
		QTextStream stream( &file );
		stream << toPlainText();
		stream.flush();
		file.close();
		document()->setModified( false );
	}
}

void QCodeEditor::saveAs( const QString& fn )
{
	auto new_fmt = path_from_qt( fn ).extension_no_dot().str();
	auto old_fmt = path_from_qt( fileName ).extension_no_dot().str();
	if ( new_fmt != old_fmt )
	{
		std::stringstream stri( toPlainText().toStdString() );
		xo::prop_node pn;
		stri >> *xo::make_serializer( old_fmt, pn );

		std::stringstream stro;
		stro << *xo::make_serializer( new_fmt, pn );

		syntaxHighlighter = new QCodeHighlighter( document(), QCodeHighlighter::detectLanguage( fn ) );
		setPlainText( QString( stro.str().c_str() ) );
	}

	fileName = fn;
	save();
}

void QCodeEditor::findDialog()
{
	QString text = QInputDialog::getText( this, "Find Text", "Text to find:", QLineEdit::Normal, findText );
	if ( !text.isNull() )
	{
		findText = text;
		moveCursor( QTextCursor::Start );
		if ( !findNext() )
			QMessageBox::warning( this, "Could not find text", "Could not find '" + findText + "'" );
	}
}

bool QCodeEditor::findNext( bool backwards )
{
	auto cursor = document()->find( findText, textCursor(), backwards ? QTextDocument::FindBackward : QTextDocument::FindFlags() );
	if ( !cursor.isNull() )
		setTextCursor( cursor );
	return !cursor.isNull();
}

QString QCodeEditor::getTitle()
{
	return QFileInfo( fileName ).fileName() + ( document()->isModified() ? "*" : "" );
}

void QCodeEditor::lineNumberAreaPaintEvent( QPaintEvent *event )
{
	QPainter painter( lineNumberArea );
	QColor c = palette().color( QWidget::backgroundRole() );
	painter.fillRect( event->rect(), c );

	QTextBlock block = firstVisibleBlock();
	int blockNumber = block.blockNumber();
	int top = (int)blockBoundingGeometry( block ).translated( contentOffset() ).top();
	int bottom = top + (int)blockBoundingRect( block ).height();

	while ( block.isValid() && top <= event->rect().bottom() ) {
		if ( block.isVisible() && bottom >= event->rect().top() ) {
			QString number = QString::number( blockNumber + 1 );
			painter.setPen( Qt::gray );
			painter.drawText( 0, top, lineNumberArea->width() - 2, fontMetrics().height(),
				Qt::AlignRight, number );
		}

		block = block.next();
		top = bottom;
		bottom = top + (int)blockBoundingRect( block ).height();
		++blockNumber;
	}
}

int QCodeEditor::lineNumberAreaWidth()
{
	int digits = 1;
	int max = qMax( 1, blockCount() );
	while ( max >= 10 ) {
		max /= 10;
		++digits;
	}

	int space = 4 + fontMetrics().width( QLatin1Char( '9' ) ) * digits;

	return space;
}

void QCodeEditor::formatDocument()
{
	auto cursor = textCursor();
	cursor.beginEditBlock();
	cursor.movePosition( QTextCursor::Start );

	auto indents = 0;
	while ( !cursor.atEnd() )
	{
		QString line = cursor.block().text();

		// count current amount of tabs
		auto tab_count = 0;
		while ( tab_count < line.size() && line[ tab_count ] == '\t' )
			++tab_count;

		auto leading_whitespace = tab_count;
		while ( leading_whitespace < line.size() && line[ leading_whitespace ].isSpace() )
			++leading_whitespace;

		QChar first_char = tab_count < line.size() ? line[ tab_count ] : QChar();
		auto desired_tabs = xo::max( 0, indents - int( first_char == '}' || first_char == ']' ) );

		if ( leading_whitespace != desired_tabs )
		{
			cursor.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, leading_whitespace );
			cursor.removeSelectedText();
			cursor.insertText( QString().fill( '\t', desired_tabs ) );
		}

		// update indents
		indents += line.count( '{' ) + line.count( '[' ) - line.count( '}' ) - line.count( ']' );

		if ( !cursor.movePosition( QTextCursor::NextBlock ) )
			break; // prevent infinite loop if this fails
	}
	cursor.endEditBlock();
}

void QCodeEditor::updateLineNumberAreaWidth( int newBlockCount )
{
	setViewportMargins( lineNumberAreaWidth(), 0, 0, 0 );
}

void QCodeEditor::updateLineNumberArea( const QRect& rect, int dy )
{
	if ( dy )
		lineNumberArea->scroll( 0, dy );
	else
		lineNumberArea->update( 0, rect.y(), lineNumberArea->width(), rect.height() );

	if ( rect.contains( viewport()->rect() ) )
		updateLineNumberAreaWidth( 0 );
}

void QCodeEditor::resizeEvent( QResizeEvent *event )
{
	QRect cr = contentsRect();
	if ( cr != previousRect ) // this is a hack to prevent a Qt bug causing infinite QResizeEvents
	{
		previousRect = cr;
		QPlainTextEdit::resizeEvent( event );
		lineNumberArea->setGeometry( QRect( cr.left(), cr.top(), lineNumberAreaWidth(), cr.height() ) );
	}
}

void QCodeEditor::keyPressEvent( QKeyEvent *e )
{
	QPlainTextEdit::keyPressEvent( e );

	switch ( language() )
	{
	case QCodeHighlighter::Language::zml:
		if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter || e->key() == '{' || e->key() == '}' )
			formatDocument();
	default:
		break;
	}
}
<|endoftext|>


<commit_before><commit_msg>UI: InterfaceMatcher: avoid nothrow_t any support matching for pointers only<commit_after><|endoftext|>


<commit_before>//===-- lldb-server.cpp -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "SystemInitializerLLGS.h"
#include "lldb/Initialization/SystemLifetimeManager.h"
#include "lldb/lldb-private.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"

#include <stdio.h>
#include <stdlib.h>

static llvm::ManagedStatic<lldb_private::SystemLifetimeManager>
    g_debugger_lifetime;

static void display_usage(const char *progname) {
  fprintf(stderr, "Usage:\n"
                  "  %s v[ersion]\n"
                  "  %s g[dbserver] [options]\n"
                  "  %s p[latform] [options]\n"
                  "Invoke subcommand for additional help\n",
          progname, progname, progname);
  exit(0);
}

// Forward declarations of subcommand main methods.
int main_gdbserver(int argc, char *argv[]);
int main_platform(int argc, char *argv[]);

static void initialize() {
  if (auto e = g_debugger_lifetime->Initialize(
          llvm::make_unique<SystemInitializerLLGS>(), nullptr))
    llvm::consumeError(std::move(e));
}

static void terminate() { g_debugger_lifetime->Terminate(); }

//----------------------------------------------------------------------
// main
//----------------------------------------------------------------------
int main(int argc, char *argv[]) {
  llvm::StringRef ToolName = argv[0];
  llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
  llvm::PrettyStackTraceProgram X(argc, argv);

  int option_error = 0;
  const char *progname = argv[0];
  if (argc < 2) {
    display_usage(progname);
    exit(option_error);
  }

  switch (argv[1][0]) {
  case 'g':
    initialize();
    main_gdbserver(argc, argv);
    terminate();
    break;
  case 'p':
    initialize();
    main_platform(argc, argv);
    terminate();
    break;
  case 'v':
    fprintf(stderr, "%s\n", lldb_private::GetVersion());
    break;
  default:
    display_usage(progname);
    exit(option_error);
  }
}
<commit_msg>[lldb-server] Use llgs namespace to avoid conflicts with Win32 API<commit_after>//===-- lldb-server.cpp -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "SystemInitializerLLGS.h"
#include "lldb/Initialization/SystemLifetimeManager.h"
#include "lldb/lldb-private.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"

#include <stdio.h>
#include <stdlib.h>

static llvm::ManagedStatic<lldb_private::SystemLifetimeManager>
    g_debugger_lifetime;

static void display_usage(const char *progname) {
  fprintf(stderr, "Usage:\n"
                  "  %s v[ersion]\n"
                  "  %s g[dbserver] [options]\n"
                  "  %s p[latform] [options]\n"
                  "Invoke subcommand for additional help\n",
          progname, progname, progname);
  exit(0);
}

// Forward declarations of subcommand main methods.
int main_gdbserver(int argc, char *argv[]);
int main_platform(int argc, char *argv[]);

namespace llgs {
static void initialize() {
  if (auto e = g_debugger_lifetime->Initialize(
          llvm::make_unique<SystemInitializerLLGS>(), nullptr))
    llvm::consumeError(std::move(e));
}

static void terminate() { g_debugger_lifetime->Terminate(); }
} // namespace llgs

//----------------------------------------------------------------------
// main
//----------------------------------------------------------------------
int main(int argc, char *argv[]) {
  llvm::StringRef ToolName = argv[0];
  llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
  llvm::PrettyStackTraceProgram X(argc, argv);

  int option_error = 0;
  const char *progname = argv[0];
  if (argc < 2) {
    display_usage(progname);
    exit(option_error);
  }

  switch (argv[1][0]) {
  case 'g':
    llgs::initialize();
    main_gdbserver(argc, argv);
    llgs::terminate();
    break;
  case 'p':
    llgs::initialize();
    main_platform(argc, argv);
    llgs::terminate();
    break;
  case 'v':
    fprintf(stderr, "%s\n", lldb_private::GetVersion());
    break;
  default:
    display_usage(progname);
    exit(option_error);
  }
}
<|endoftext|>