<commit_before>//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SubtargetFeature interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
#include <cassert>
#include <cctype>
using namespace llvm;

//===----------------------------------------------------------------------===//
//                          Static Helper Functions
//===----------------------------------------------------------------------===//

/// hasFlag - Determine if a feature has a flag; '+' or '-'
///
static inline bool hasFlag(const std::string &Feature) {
  assert(!Feature.empty() && "Empty string");
  // Get first character
  char Ch = Feature[0];
  // Check if first character is '+' or '-' flag
  return Ch == '+' || Ch =='-';
}

/// StripFlag - Return string stripped of flag.
///
static inline std::string StripFlag(const std::string &Feature) {
  return hasFlag(Feature) ? Feature.substr(1) : Feature;
}

/// isEnabled - Return true if enable flag; '+'.
///
static inline bool isEnabled(const std::string &Feature) {
  assert(!Feature.empty() && "Empty string");
  // Get first character
  char Ch = Feature[0];
  // Check if first character is '+' for enabled
  return Ch == '+';
}

/// PrependFlag - Return a string with a prepended flag; '+' or '-'.
///
static inline std::string PrependFlag(const std::string &Feature,
                                      bool IsEnabled) {
  assert(!Feature.empty() && "Empty string");
  if (hasFlag(Feature)) return Feature;
  return std::string(IsEnabled ? "+" : "-") + Feature;
}

/// Split - Splits a string of comma separated items in to a vector of strings.
///
static void Split(std::vector<std::string> &V, const std::string &S) {
  // Start at beginning of string.
  size_t Pos = 0;
  while (true) {
    // Find the next comma
    size_t Comma = S.find(',', Pos);
    // If no comma found then the the rest of the string is used
    if (Comma == std::string::npos) {
      // Add string to vector
      V.push_back(S.substr(Pos));
      break;
    }
    // Otherwise add substring to vector
    V.push_back(S.substr(Pos, Comma - Pos));
    // Advance to next item
    Pos = Comma + 1;
  }
}

/// Join a vector of strings to a string with a comma separating each element.
///
static std::string Join(const std::vector<std::string> &V) {
  // Start with empty string.
  std::string Result;
  // If the vector is not empty
  if (!V.empty()) {
    // Start with the CPU feature
    Result = V[0];
    // For each successive feature
    for (size_t i = 1; i < V.size(); i++) {
      // Add a comma
      Result += ",";
      // Add the feature
      Result += V[i];
    }
  }
  // Return the features string
  return Result;
}

/// Adding features.
void SubtargetFeatures::AddFeature(const std::string &String,
                                   bool IsEnabled) {
  // Don't add empty features
  if (!String.empty()) {
    // Convert to lowercase, prepend flag and add to vector
    Features.push_back(PrependFlag(LowercaseString(String), IsEnabled));
  }
}

/// Find KV in array using binary search.
template<typename T> const T *Find(const std::string &S, const T *A, size_t L) {
  // Make the lower bound element we're looking for
  T KV;
  KV.Key = S.c_str();
  // Determine the end of the array
  const T *Hi = A + L;
  // Binary search the array
  const T *F = std::lower_bound(A, Hi, KV);
  // If not found then return NULL
  if (F == Hi || std::string(F->Key) != S) return NULL;
  // Return the found array item
  return F;
}

/// getLongestEntryLength - Return the length of the longest entry in the table.
///
static size_t getLongestEntryLength(const SubtargetFeatureKV *Table,
                                    size_t Size) {
  size_t MaxLen = 0;
  for (size_t i = 0; i < Size; i++)
    MaxLen = std::max(MaxLen, std::strlen(Table[i].Key));
  return MaxLen;
}

/// Display help for feature choices.
///
static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize,
                 const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) {
  // Determine the length of the longest CPU and Feature entries.
  unsigned MaxCPULen  = getLongestEntryLength(CPUTable, CPUTableSize);
  unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize);

  // Print the CPU table.
  errs() << "Available CPUs for this target:\n\n";
  for (size_t i = 0; i != CPUTableSize; i++)
    errs() << "  " << CPUTable[i].Key
         << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ')
         << " - " << CPUTable[i].Desc << ".\n";
  errs() << "\n";

  // Print the Feature table.
  errs() << "Available features for this target:\n\n";
  for (size_t i = 0; i != FeatTableSize; i++)
    errs() << "  " << FeatTable[i].Key
         << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ')
         << " - " << FeatTable[i].Desc << ".\n";
  errs() << "\n";

  errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
       << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
  exit(1);
}

//===----------------------------------------------------------------------===//
//                    SubtargetFeatures Implementation
//===----------------------------------------------------------------------===//

SubtargetFeatures::SubtargetFeatures(const std::string &Initial) {
  // Break up string into separate features
  Split(Features, Initial);
}

std::string SubtargetFeatures::getString() const {
  return Join(Features);
}
void SubtargetFeatures::setString(const std::string &Initial) {
  // Throw out old features
  Features.clear();
  // Break up string into separate features
  Split(Features, LowercaseString(Initial));
}

/// setCPU - Set the CPU string.  Replaces previous setting.  Setting to ""
/// clears CPU.
void SubtargetFeatures::setCPU(const std::string &String) {
  Features[0] = LowercaseString(String);
}

/// setCPUIfNone - Setting CPU string only if no string is set.
///
void SubtargetFeatures::setCPUIfNone(const std::string &String) {
  if (Features[0].empty()) setCPU(String);
}

/// getCPU - Returns current CPU.
///
const std::string & SubtargetFeatures::getCPU() const {
  return Features[0];
}

/// SetImpliedBits - For each feature that is (transitively) implied by this
/// feature, set it.
///
static
void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry,
                    const SubtargetFeatureKV *FeatureTable,
                    size_t FeatureTableSize) {
  for (size_t i = 0; i < FeatureTableSize; ++i) {
    const SubtargetFeatureKV &FE = FeatureTable[i];

    if (FeatureEntry->Value == FE.Value) continue;

    if (FeatureEntry->Implies & FE.Value) {
      Bits |= FE.Value;
      SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  }
}

/// ClearImpliedBits - For each feature that (transitively) implies this
/// feature, clear it.
///
static
void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry,
                      const SubtargetFeatureKV *FeatureTable,
                      size_t FeatureTableSize) {
  for (size_t i = 0; i < FeatureTableSize; ++i) {
    const SubtargetFeatureKV &FE = FeatureTable[i];

    if (FeatureEntry->Value == FE.Value) continue;

    if (FE.Implies & FeatureEntry->Value) {
      Bits &= ~FE.Value;
      ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  }
}

/// getBits - Get feature bits.
///
uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable,
                                          size_t CPUTableSize,
                                    const SubtargetFeatureKV *FeatureTable,
                                          size_t FeatureTableSize) {
  assert(CPUTable && "missing CPU table");
  assert(FeatureTable && "missing features table");
#ifndef NDEBUG
  for (size_t i = 1; i < CPUTableSize; i++) {
    assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 &&
           "CPU table is not sorted");
  }
  for (size_t i = 1; i < FeatureTableSize; i++) {
    assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 &&
          "CPU features table is not sorted");
  }
#endif
  uint32_t Bits = 0;                    // Resulting bits

  // Check if help is needed
  if (Features[0] == "help")
    Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);

  // Find CPU entry
  const SubtargetFeatureKV *CPUEntry =
                            Find(Features[0], CPUTable, CPUTableSize);
  // If there is a match
  if (CPUEntry) {
    // Set base feature bits
    Bits = CPUEntry->Value;

    // Set the feature implied by this CPU feature, if any.
    for (size_t i = 0; i < FeatureTableSize; ++i) {
      const SubtargetFeatureKV &FE = FeatureTable[i];
      if (CPUEntry->Value & FE.Value)
        SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  } else {
    errs() << "'" << Features[0]
           << "' is not a recognized processor for this target"
           << " (ignoring processor)\n";
  }
  // Iterate through each feature
  for (size_t i = 1; i < Features.size(); i++) {
    const std::string &Feature = Features[i];

    // Check for help
    if (Feature == "+help")
      Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);

    // Find feature in table.
    const SubtargetFeatureKV *FeatureEntry =
                       Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
    // If there is a match
    if (FeatureEntry) {
      // Enable/disable feature in bits
      if (isEnabled(Feature)) {
        Bits |=  FeatureEntry->Value;

        // For each feature that this implies, set it.
        SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
      } else {
        Bits &= ~FeatureEntry->Value;

        // For each feature that implies this, clear it.
        ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
      }
    } else {
      errs() << "'" << Feature
             << "' is not a recognized feature for this target"
             << " (ignoring feature)\n";
    }
  }

  return Bits;
}

/// Get info pointer
void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table,
                                       size_t TableSize) {
  assert(Table && "missing table");
#ifndef NDEBUG
  for (size_t i = 1; i < TableSize; i++) {
    assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted");
  }
#endif

  // Find entry
  const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize);

  if (Entry) {
    return Entry->Value;
  } else {
    errs() << "'" << Features[0]
           << "' is not a recognized processor for this target"
           << " (ignoring processor)\n";
    return NULL;
  }
}

/// print - Print feature string.
///
void SubtargetFeatures::print(raw_ostream &OS) const {
  for (size_t i = 0, e = Features.size(); i != e; ++i)
    OS << Features[i] << "  ";
  OS << "\n";
}

/// dump - Dump feature info.
///
void SubtargetFeatures::dump() const {
  print(errs());
}

/// getDefaultSubtargetFeatures - Return a string listing
/// the features associated with the target triple.
///
/// FIXME: This is an inelegant way of specifying the features of a
/// subtarget. It would be better if we could encode this information
/// into the IR. See <rdar://5972456>.
///
std::string SubtargetFeatures::getDefaultSubtargetFeatures(
                                               const Triple& Triple) {
  switch (Triple.getVendor()) {
  case Triple::Apple:
    switch (Triple.getArch()) {
    case Triple::ppc:   // powerpc-apple-*
      return std::string("altivec");
    case Triple::ppc64: // powerpc64-apple-*
      return std::string("64bit,altivec");
    default:
      break;
    }
    break;
  default:
    break;
  }

  return std::string("");
}
<commit_msg>Change errs() to dbgs().<commit_after>//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SubtargetFeature interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
#include <cassert>
#include <cctype>
using namespace llvm;

//===----------------------------------------------------------------------===//
//                          Static Helper Functions
//===----------------------------------------------------------------------===//

/// hasFlag - Determine if a feature has a flag; '+' or '-'
///
static inline bool hasFlag(const std::string &Feature) {
  assert(!Feature.empty() && "Empty string");
  // Get first character
  char Ch = Feature[0];
  // Check if first character is '+' or '-' flag
  return Ch == '+' || Ch =='-';
}

/// StripFlag - Return string stripped of flag.
///
static inline std::string StripFlag(const std::string &Feature) {
  return hasFlag(Feature) ? Feature.substr(1) : Feature;
}

/// isEnabled - Return true if enable flag; '+'.
///
static inline bool isEnabled(const std::string &Feature) {
  assert(!Feature.empty() && "Empty string");
  // Get first character
  char Ch = Feature[0];
  // Check if first character is '+' for enabled
  return Ch == '+';
}

/// PrependFlag - Return a string with a prepended flag; '+' or '-'.
///
static inline std::string PrependFlag(const std::string &Feature,
                                      bool IsEnabled) {
  assert(!Feature.empty() && "Empty string");
  if (hasFlag(Feature)) return Feature;
  return std::string(IsEnabled ? "+" : "-") + Feature;
}

/// Split - Splits a string of comma separated items in to a vector of strings.
///
static void Split(std::vector<std::string> &V, const std::string &S) {
  // Start at beginning of string.
  size_t Pos = 0;
  while (true) {
    // Find the next comma
    size_t Comma = S.find(',', Pos);
    // If no comma found then the the rest of the string is used
    if (Comma == std::string::npos) {
      // Add string to vector
      V.push_back(S.substr(Pos));
      break;
    }
    // Otherwise add substring to vector
    V.push_back(S.substr(Pos, Comma - Pos));
    // Advance to next item
    Pos = Comma + 1;
  }
}

/// Join a vector of strings to a string with a comma separating each element.
///
static std::string Join(const std::vector<std::string> &V) {
  // Start with empty string.
  std::string Result;
  // If the vector is not empty
  if (!V.empty()) {
    // Start with the CPU feature
    Result = V[0];
    // For each successive feature
    for (size_t i = 1; i < V.size(); i++) {
      // Add a comma
      Result += ",";
      // Add the feature
      Result += V[i];
    }
  }
  // Return the features string
  return Result;
}

/// Adding features.
void SubtargetFeatures::AddFeature(const std::string &String,
                                   bool IsEnabled) {
  // Don't add empty features
  if (!String.empty()) {
    // Convert to lowercase, prepend flag and add to vector
    Features.push_back(PrependFlag(LowercaseString(String), IsEnabled));
  }
}

/// Find KV in array using binary search.
template<typename T> const T *Find(const std::string &S, const T *A, size_t L) {
  // Make the lower bound element we're looking for
  T KV;
  KV.Key = S.c_str();
  // Determine the end of the array
  const T *Hi = A + L;
  // Binary search the array
  const T *F = std::lower_bound(A, Hi, KV);
  // If not found then return NULL
  if (F == Hi || std::string(F->Key) != S) return NULL;
  // Return the found array item
  return F;
}

/// getLongestEntryLength - Return the length of the longest entry in the table.
///
static size_t getLongestEntryLength(const SubtargetFeatureKV *Table,
                                    size_t Size) {
  size_t MaxLen = 0;
  for (size_t i = 0; i < Size; i++)
    MaxLen = std::max(MaxLen, std::strlen(Table[i].Key));
  return MaxLen;
}

/// Display help for feature choices.
///
static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize,
                 const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) {
  // Determine the length of the longest CPU and Feature entries.
  unsigned MaxCPULen  = getLongestEntryLength(CPUTable, CPUTableSize);
  unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize);

  // Print the CPU table.
  errs() << "Available CPUs for this target:\n\n";
  for (size_t i = 0; i != CPUTableSize; i++)
    errs() << "  " << CPUTable[i].Key
         << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ')
         << " - " << CPUTable[i].Desc << ".\n";
  errs() << "\n";

  // Print the Feature table.
  errs() << "Available features for this target:\n\n";
  for (size_t i = 0; i != FeatTableSize; i++)
    errs() << "  " << FeatTable[i].Key
         << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ')
         << " - " << FeatTable[i].Desc << ".\n";
  errs() << "\n";

  errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
       << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
  exit(1);
}

//===----------------------------------------------------------------------===//
//                    SubtargetFeatures Implementation
//===----------------------------------------------------------------------===//

SubtargetFeatures::SubtargetFeatures(const std::string &Initial) {
  // Break up string into separate features
  Split(Features, Initial);
}

std::string SubtargetFeatures::getString() const {
  return Join(Features);
}
void SubtargetFeatures::setString(const std::string &Initial) {
  // Throw out old features
  Features.clear();
  // Break up string into separate features
  Split(Features, LowercaseString(Initial));
}

/// setCPU - Set the CPU string.  Replaces previous setting.  Setting to ""
/// clears CPU.
void SubtargetFeatures::setCPU(const std::string &String) {
  Features[0] = LowercaseString(String);
}

/// setCPUIfNone - Setting CPU string only if no string is set.
///
void SubtargetFeatures::setCPUIfNone(const std::string &String) {
  if (Features[0].empty()) setCPU(String);
}

/// getCPU - Returns current CPU.
///
const std::string & SubtargetFeatures::getCPU() const {
  return Features[0];
}

/// SetImpliedBits - For each feature that is (transitively) implied by this
/// feature, set it.
///
static
void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry,
                    const SubtargetFeatureKV *FeatureTable,
                    size_t FeatureTableSize) {
  for (size_t i = 0; i < FeatureTableSize; ++i) {
    const SubtargetFeatureKV &FE = FeatureTable[i];

    if (FeatureEntry->Value == FE.Value) continue;

    if (FeatureEntry->Implies & FE.Value) {
      Bits |= FE.Value;
      SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  }
}

/// ClearImpliedBits - For each feature that (transitively) implies this
/// feature, clear it.
///
static
void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry,
                      const SubtargetFeatureKV *FeatureTable,
                      size_t FeatureTableSize) {
  for (size_t i = 0; i < FeatureTableSize; ++i) {
    const SubtargetFeatureKV &FE = FeatureTable[i];

    if (FeatureEntry->Value == FE.Value) continue;

    if (FE.Implies & FeatureEntry->Value) {
      Bits &= ~FE.Value;
      ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  }
}

/// getBits - Get feature bits.
///
uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable,
                                          size_t CPUTableSize,
                                    const SubtargetFeatureKV *FeatureTable,
                                          size_t FeatureTableSize) {
  assert(CPUTable && "missing CPU table");
  assert(FeatureTable && "missing features table");
#ifndef NDEBUG
  for (size_t i = 1; i < CPUTableSize; i++) {
    assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 &&
           "CPU table is not sorted");
  }
  for (size_t i = 1; i < FeatureTableSize; i++) {
    assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 &&
          "CPU features table is not sorted");
  }
#endif
  uint32_t Bits = 0;                    // Resulting bits

  // Check if help is needed
  if (Features[0] == "help")
    Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);

  // Find CPU entry
  const SubtargetFeatureKV *CPUEntry =
                            Find(Features[0], CPUTable, CPUTableSize);
  // If there is a match
  if (CPUEntry) {
    // Set base feature bits
    Bits = CPUEntry->Value;

    // Set the feature implied by this CPU feature, if any.
    for (size_t i = 0; i < FeatureTableSize; ++i) {
      const SubtargetFeatureKV &FE = FeatureTable[i];
      if (CPUEntry->Value & FE.Value)
        SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  } else {
    errs() << "'" << Features[0]
           << "' is not a recognized processor for this target"
           << " (ignoring processor)\n";
  }
  // Iterate through each feature
  for (size_t i = 1; i < Features.size(); i++) {
    const std::string &Feature = Features[i];

    // Check for help
    if (Feature == "+help")
      Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);

    // Find feature in table.
    const SubtargetFeatureKV *FeatureEntry =
                       Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
    // If there is a match
    if (FeatureEntry) {
      // Enable/disable feature in bits
      if (isEnabled(Feature)) {
        Bits |=  FeatureEntry->Value;

        // For each feature that this implies, set it.
        SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
      } else {
        Bits &= ~FeatureEntry->Value;

        // For each feature that implies this, clear it.
        ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
      }
    } else {
      errs() << "'" << Feature
             << "' is not a recognized feature for this target"
             << " (ignoring feature)\n";
    }
  }

  return Bits;
}

/// Get info pointer
void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table,
                                       size_t TableSize) {
  assert(Table && "missing table");
#ifndef NDEBUG
  for (size_t i = 1; i < TableSize; i++) {
    assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted");
  }
#endif

  // Find entry
  const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize);

  if (Entry) {
    return Entry->Value;
  } else {
    errs() << "'" << Features[0]
           << "' is not a recognized processor for this target"
           << " (ignoring processor)\n";
    return NULL;
  }
}

/// print - Print feature string.
///
void SubtargetFeatures::print(raw_ostream &OS) const {
  for (size_t i = 0, e = Features.size(); i != e; ++i)
    OS << Features[i] << "  ";
  OS << "\n";
}

/// dump - Dump feature info.
///
void SubtargetFeatures::dump() const {
  print(dbgs());
}

/// getDefaultSubtargetFeatures - Return a string listing
/// the features associated with the target triple.
///
/// FIXME: This is an inelegant way of specifying the features of a
/// subtarget. It would be better if we could encode this information
/// into the IR. See <rdar://5972456>.
///
std::string SubtargetFeatures::getDefaultSubtargetFeatures(
                                               const Triple& Triple) {
  switch (Triple.getVendor()) {
  case Triple::Apple:
    switch (Triple.getArch()) {
    case Triple::ppc:   // powerpc-apple-*
      return std::string("altivec");
    case Triple::ppc64: // powerpc64-apple-*
      return std::string("64bit,altivec");
    default:
      break;
    }
    break;
  default:
    break;
  }

  return std::string("");
}
<|endoftext|>


<commit_before>#include "capstone_wrapper.h"
#include <windows.h>

csh Capstone::mHandle = 0;

void Capstone::GlobalInitialize()
{
#ifdef _WIN64
    cs_open(CS_ARCH_X86, CS_MODE_64, &mHandle);
#else //x86
    cs_open(CS_ARCH_X86, CS_MODE_32, &mHandle);
#endif //_WIN64
    cs_option(mHandle, CS_OPT_DETAIL, CS_OPT_ON);
}

void Capstone::GlobalFinalize()
{
    if(mHandle) //close handle
        cs_close(&mHandle);
}

Capstone::Capstone()
{
	mInstr = cs_malloc(mHandle);
    mSuccess = false;
}

Capstone::~Capstone()
{
    if(mInstr) //free last disassembled instruction
        cs_free(mInstr, 1);
}

bool Capstone::Disassemble(size_t addr, const unsigned char data[MAX_DISASM_BUFFER])
{
    return Disassemble(addr, data, MAX_DISASM_BUFFER);
}

bool Capstone::Disassemble(size_t addr, const unsigned char* data, int size)
{
	if (!data)
		return false;

	size_t codeSize = size;
	uint64_t addr64 = addr;

	return (mSuccess = cs_disasm_iter(mHandle, &data, &codeSize, &addr64, mInstr));
}

const cs_insn* Capstone::GetInstr() const
{
    if(!Success())
        return nullptr;
    return mInstr;
}

bool Capstone::Success() const
{
    return mSuccess;
}

const char* Capstone::RegName(x86_reg reg) const
{
    return cs_reg_name(mHandle, reg);
}

bool Capstone::InGroup(cs_group_type group) const
{
    if(!Success())
        return false;
    return cs_insn_group(mHandle, mInstr, group);
}

std::string Capstone::OperandText(int opindex) const
{
    if(!Success() || opindex >= mInstr->detail->x86.op_count)
        return "";
    const auto & op = mInstr->detail->x86.operands[opindex];
    std::string result;
    char temp[32] = "";
    switch(op.type)
    {
    case X86_OP_REG:
    {
        result = RegName(x86_reg(op.reg));
    }
    break;

    case X86_OP_IMM:
    {
        sprintf_s(temp, "%llX", op.imm);
        result = temp;
    }
    break;

    case X86_OP_MEM:
    {
        const auto & mem = op.mem;
        if(op.mem.base == X86_REG_RIP)  //rip-relative
        {
            sprintf_s(temp, "%llX", Address() + op.mem.disp + Size());
            result += temp;
        }
        else //normal
        {
            bool prependPlus = false;
            if(mem.base)
            {
                result += RegName(x86_reg(mem.base));
                prependPlus = true;
            }
            if(mem.index)
            {
                if(prependPlus)
                    result += "+";
                result += RegName(x86_reg(mem.index));
                sprintf_s(temp, "*%X", mem.scale);
                result += temp;
                prependPlus = true;
            }
            if(mem.disp)
            {
                char operatorText = '+';
                if(mem.disp < 0)
                {
                    operatorText = '-';
                    sprintf_s(temp, "%llX", mem.disp * -1);
                }
                else
                    sprintf_s(temp, "%llX", mem.disp);
                if(prependPlus)
                    result += operatorText;
                result += temp;
            }
        }
    }
    break;

    case X86_OP_FP:
    case X86_OP_INVALID:
    {
    }
    break;
    }
    return result;
}

int Capstone::Size() const
{
    if(!Success())
        return 1;
    return GetInstr()->size;
}

size_t Capstone::Address() const
{
    if(!Success())
        return 0;
    return size_t(GetInstr()->address);
}

const cs_x86 & Capstone::x86() const
{
    if(!Success())
        DebugBreak();
    return GetInstr()->detail->x86;
}

bool Capstone::IsFilling() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_NOP:
    case X86_INS_INT3:
        return true;
    default:
        return false;
    }
}

bool Capstone::IsLoop() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_LOOP:
    case X86_INS_LOOPE:
    case X86_INS_LOOPNE:
        return true;
    default:
        return false;
    }
}

x86_insn Capstone::GetId() const
{
    if(!Success())
        DebugBreak();
    return x86_insn(mInstr->id);
}

std::string Capstone::InstructionText() const
{
    if(!Success())
        return "???";
    std::string result = Mnemonic();
    if(OpCount())
    {
        result += " ";
        result += mInstr->op_str;
    }
    return result;
}

int Capstone::OpCount() const
{
    if(!Success())
        return 0;
    return x86().op_count;
}

cs_x86_op Capstone::operator[](int index) const
{
    if(!Success() || index >= OpCount())
        DebugBreak();
    return x86().operands[index];
}

bool Capstone::IsNop() const
{
    return GetId() == X86_INS_NOP;
}

bool Capstone::IsInt3() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_INT3:
        return true;
    case X86_INS_INT:
    {
        cs_x86_op op = x86().operands[0];
        return op.type == X86_OP_IMM && op.imm == 3;
    }
    default:
        return false;
    }
}

std::string Capstone::Mnemonic() const
{
    if(!Success())
        return "???";
    return mInstr->mnemonic;
}

const char* Capstone::MemSizeName(int size) const
{
    switch(size)
    {
    case 1:
        return "byte";
    case 2:
        return "word";
    case 4:
        return "dword";
    case 6:
        return "fword";
    case 8:
        return "qword";
    case 10:
        return "tword";
    case 16:
        return "dqword";
    case 32:
        return "yword";
    case 64:
        return "zword";
    default:
        return nullptr;
    }
}

size_t Capstone::BranchDestination() const
{
    if(!Success())
        return 0;
    if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop())
    {
        const auto & op = x86().operands[0];
        if(op.type == CS_OP_IMM)
            return size_t(op.imm);
    }
    return 0;
}<commit_msg>formatting<commit_after>#include "capstone_wrapper.h"
#include <windows.h>

csh Capstone::mHandle = 0;

void Capstone::GlobalInitialize()
{
#ifdef _WIN64
    cs_open(CS_ARCH_X86, CS_MODE_64, &mHandle);
#else //x86
    cs_open(CS_ARCH_X86, CS_MODE_32, &mHandle);
#endif //_WIN64
    cs_option(mHandle, CS_OPT_DETAIL, CS_OPT_ON);
}

void Capstone::GlobalFinalize()
{
    if(mHandle) //close handle
        cs_close(&mHandle);
}

Capstone::Capstone()
{
    mInstr = cs_malloc(mHandle);
    mSuccess = false;
}

Capstone::~Capstone()
{
    if(mInstr) //free last disassembled instruction
        cs_free(mInstr, 1);
}

bool Capstone::Disassemble(size_t addr, const unsigned char data[MAX_DISASM_BUFFER])
{
    return Disassemble(addr, data, MAX_DISASM_BUFFER);
}

bool Capstone::Disassemble(size_t addr, const unsigned char* data, int size)
{
    if(!data)
        return false;

    size_t codeSize = size;
    uint64_t addr64 = addr;

    return (mSuccess = cs_disasm_iter(mHandle, &data, &codeSize, &addr64, mInstr));
}

const cs_insn* Capstone::GetInstr() const
{
    if(!Success())
        return nullptr;
    return mInstr;
}

bool Capstone::Success() const
{
    return mSuccess;
}

const char* Capstone::RegName(x86_reg reg) const
{
    return cs_reg_name(mHandle, reg);
}

bool Capstone::InGroup(cs_group_type group) const
{
    if(!Success())
        return false;
    return cs_insn_group(mHandle, mInstr, group);
}

std::string Capstone::OperandText(int opindex) const
{
    if(!Success() || opindex >= mInstr->detail->x86.op_count)
        return "";
    const auto & op = mInstr->detail->x86.operands[opindex];
    std::string result;
    char temp[32] = "";
    switch(op.type)
    {
    case X86_OP_REG:
    {
        result = RegName(x86_reg(op.reg));
    }
    break;

    case X86_OP_IMM:
    {
        sprintf_s(temp, "%llX", op.imm);
        result = temp;
    }
    break;

    case X86_OP_MEM:
    {
        const auto & mem = op.mem;
        if(op.mem.base == X86_REG_RIP)  //rip-relative
        {
            sprintf_s(temp, "%llX", Address() + op.mem.disp + Size());
            result += temp;
        }
        else //normal
        {
            bool prependPlus = false;
            if(mem.base)
            {
                result += RegName(x86_reg(mem.base));
                prependPlus = true;
            }
            if(mem.index)
            {
                if(prependPlus)
                    result += "+";
                result += RegName(x86_reg(mem.index));
                sprintf_s(temp, "*%X", mem.scale);
                result += temp;
                prependPlus = true;
            }
            if(mem.disp)
            {
                char operatorText = '+';
                if(mem.disp < 0)
                {
                    operatorText = '-';
                    sprintf_s(temp, "%llX", mem.disp * -1);
                }
                else
                    sprintf_s(temp, "%llX", mem.disp);
                if(prependPlus)
                    result += operatorText;
                result += temp;
            }
        }
    }
    break;

    case X86_OP_FP:
    case X86_OP_INVALID:
    {
    }
    break;
    }
    return result;
}

int Capstone::Size() const
{
    if(!Success())
        return 1;
    return GetInstr()->size;
}

size_t Capstone::Address() const
{
    if(!Success())
        return 0;
    return size_t(GetInstr()->address);
}

const cs_x86 & Capstone::x86() const
{
    if(!Success())
        DebugBreak();
    return GetInstr()->detail->x86;
}

bool Capstone::IsFilling() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_NOP:
    case X86_INS_INT3:
        return true;
    default:
        return false;
    }
}

bool Capstone::IsLoop() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_LOOP:
    case X86_INS_LOOPE:
    case X86_INS_LOOPNE:
        return true;
    default:
        return false;
    }
}

x86_insn Capstone::GetId() const
{
    if(!Success())
        DebugBreak();
    return x86_insn(mInstr->id);
}

std::string Capstone::InstructionText() const
{
    if(!Success())
        return "???";
    std::string result = Mnemonic();
    if(OpCount())
    {
        result += " ";
        result += mInstr->op_str;
    }
    return result;
}

int Capstone::OpCount() const
{
    if(!Success())
        return 0;
    return x86().op_count;
}

cs_x86_op Capstone::operator[](int index) const
{
    if(!Success() || index >= OpCount())
        DebugBreak();
    return x86().operands[index];
}

bool Capstone::IsNop() const
{
    return GetId() == X86_INS_NOP;
}

bool Capstone::IsInt3() const
{
    if(!Success())
        return false;
    switch(GetId())
    {
    case X86_INS_INT3:
        return true;
    case X86_INS_INT:
    {
        cs_x86_op op = x86().operands[0];
        return op.type == X86_OP_IMM && op.imm == 3;
    }
    default:
        return false;
    }
}

std::string Capstone::Mnemonic() const
{
    if(!Success())
        return "???";
    return mInstr->mnemonic;
}

const char* Capstone::MemSizeName(int size) const
{
    switch(size)
    {
    case 1:
        return "byte";
    case 2:
        return "word";
    case 4:
        return "dword";
    case 6:
        return "fword";
    case 8:
        return "qword";
    case 10:
        return "tword";
    case 16:
        return "dqword";
    case 32:
        return "yword";
    case 64:
        return "zword";
    default:
        return nullptr;
    }
}

size_t Capstone::BranchDestination() const
{
    if(!Success())
        return 0;
    if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop())
    {
        const auto & op = x86().operands[0];
        if(op.type == CS_OP_IMM)
            return size_t(op.imm);
    }
    return 0;
}<|endoftext|>


<commit_before>#include "Console.hpp"

#include <algorithm>
#include <sstream>

#include <Windows.h>
#include <conio.h> // _getch()
#pragma warning(disable:4996)

#include <io.h>
#include <cctype> //isgraph

#define ps1beg "\xAF["
#define ps1end "]\xAE"

// Utils
namespace
{
    std::vector<std::string> SplitString(const std::string &String, char Delimiter)
    {
        std::vector<std::string> SplitString;
        std::stringstream StringStream(String);
        std::string Token;
        while( std::getline(StringStream, Token, Delimiter) )
        {
            SplitString.push_back(Token);
        }
        return SplitString;
    }
}

namespace Console
{
    Console::Console()
    {
        ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleOutputCP(437);

        CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo{};
        if( GetConsoleScreenBufferInfo(ConsoleHandle, &ConsoleInfo) )
        {
            ConsoleWidth = ConsoleInfo.dwSize.X;
        }

        SetTextColor(Color::Info);

        PushCommand("help", std::make_shared<Help>());
        PushCommand("history", std::make_shared<History>());
        PushCommand("quit", std::make_shared<Quit>());
    }

    std::string Console::NearestCommand(const std::string & Command) const
    {
        if( !Command.empty() )
        {
            // Find closest matching command
            std::vector<std::string> Suggestions;

            for( const auto &Cmd : Commands )
            {
                if( !Command.compare(0, Command.length(), (Cmd.first), 0, Command.length()) )
                {
                    Suggestions.push_back((Cmd.first));
                }
            }

            if( Suggestions.size() )
            {
                // Return first match, for now
                return Suggestions.front();
            }
        }
        return "";
    }

    Console::~Console()
    {
        Commands.clear();
    }

    void Console::HandleInput(uint32_t KeyCode)
    {
        switch( KeyCode )
        {
        case '\r': // Enter
        {
            SetTextColor(Color::Info);
            // Clear previous suggestion
            if( !CurSuggestion.empty() )
            {
                std::cout.width(CurSuggestion.length());
                std::cout.fill(' ');
                std::cout << "";

                std::cout.width(CurSuggestion.length());
                std::cout.fill('\b');
                std::cout << "";
            }

            std::cout << ps1end << std::endl;

            std::string Command = CurCommand.substr(0, CurCommand.find_first_of(' '));

            if( !Command.empty() )
            {
                // Run command if it exists
                if( Commands.count(Command)
                    && Commands[Command] )
                {
                    if( !Commands[Command]->Run(SplitString(CurCommand, ' ')) )
                    {
                        // Error running command;
                        SetTextColor(Color::Error);
                        std::cout << "Invalid Usage: " << Command << std::endl;
                        SetTextColor(Color::Info);
                        std::cout << Commands[Command]->Info() << std::endl;
                    }
                }
                else
                {
                    SetTextColor(Color::Error);
                    std::cout << "Unknown Command: " << Command << std::endl;
                }

                // Add to history
                PrevCommands.push_back(CurCommand);
                PrevCommand = PrevCommands.end();
                CurCommand.clear();
                CurSuggestion.clear();
            }

            SetTextColor(Color::Info);
            break;
        }
        case '\t': // Tab
        {
            // Tab completion
            if( !CurSuggestion.empty() && !CurCommand.empty() )
            {
                CurCommand = CurSuggestion;
            }
            break;
        }
        case '\x16': // Ctrl + V
        {
            // Paste in clipbard
            if( OpenClipboard(nullptr) )
            {
                std::string Clipboard(reinterpret_cast<char*>(GetClipboardData(CF_TEXT)));
                CloseClipboard();
                for( const char &CurChar : Clipboard )
                {
                    HandleInput(CurChar);
                }
            }
            break;
        }
        case 0x00: // Function Keys
        case 0xE0:
        {
            uint32_t Func = _getch();
            switch( Func )
            {
            case 0x48: // Up
            {
                if( !PrevCommands.empty() )
                {
                    if( PrevCommand != PrevCommands.begin() )
                    {
                        PrevCommand--;
                    }

                    CurCommand = *PrevCommand;
                }
                break;
            }
            case 0x50: // Down
            {
                if( !PrevCommands.empty() )
                {
                    if( PrevCommand != PrevCommands.end() && PrevCommand != PrevCommands.end() - 1 )
                    {
                        PrevCommand++;
                        CurCommand = *PrevCommand;
                    }
                    else if( PrevCommand == PrevCommands.end() - 1 )
                    {
                        PrevCommand++;
                        CurCommand.clear();
                    }
                    else
                    {
                        CurCommand.clear();
                    }
                }
                break;
            }
            }
            break;
        }
        case '\b': // Backspace
        {
            if( !CurCommand.empty() )
            {
                // Remove character from current command
                CurCommand.pop_back();
                // Update Suggestion
                CurSuggestion = NearestCommand(CurCommand);
            }
            break;
        }
        default: // Every other character (alphanum and space)
        {
            if( std::isgraph(KeyCode) || std::isspace(KeyCode) )
            {
                CurCommand.push_back(static_cast<uint8_t>(KeyCode));

                // Update Suggestion
                CurSuggestion = NearestCommand(CurCommand);
            }
            break;
        }
        }
    }

    void Console::PrintLine()
    {
        SetTextColor(Color::Info);
        std::cout << '\r';
        std::cout.width(ConsoleWidth - 1);
        std::cout.fill(' ');
        std::cout << '\r' << ps1beg;
        SetTextColor(Color::Input);

        if( CurSuggestion.length() )
        {
            // Print suggestion
            SetTextColor(Color::Suggestion);
            std::cout << CurSuggestion;
            // Go back
            std::cout.width(CurSuggestion.length());
            std::cout.fill('\b');
            std::cout << "";
        }
        // Print currently typed in command
        SetTextColor(Color::Input);
        std::cout << CurCommand;
        std::cout.flush();
    }

    void Console::PushCommand(const std::string &CommandName, std::shared_ptr<Command> Command)
    {
        Commands[CommandName] = Command;
    }
    void Console::PopCommand(const std::string &CommandName)
    {
        if( Commands.count(CommandName) )
        {
            Commands.erase(CommandName);
        }
    }

    /// Meta commands

    // Help
    Console::Help::Help()
    {
    }

    Console::Help::~Help()
    {
    }

    bool Console::Help::Run(const std::vector<std::string> &Arguments)
    {
        if( Arguments.size() >= 2 )
        {
            if( Console::Instance()->Commands.count(Arguments[1]) )
            {
                if( Arguments.size() == 3 )
                {
                    std::cout << Console::Instance()->Commands[Arguments[1]]->Info() << std::endl;
                }
                else
                {
                    std::cout << Console::Instance()->Commands[Arguments[1]]->Info(Arguments.back()) << std::endl;
                }
            }
            else
            {
                SetTextColor(Color::Error);
                std::cout << "Command: " << Arguments[1] << " not found." << std::endl;
            }
        }
        else
        {
            // Show all command info
            for( const auto &Command : Console::Instance()->Commands )
            {
                std::string Padded(Command.first);
                Padded.resize(Console::Instance()->ConsoleWidth / 2, '\xC4');
                SetTextColor(Color::Info);
                std::cout << Padded << std::endl;
                SetTextColor(Color::Info^Color::Bright);
                std::cout << Command.second->Info(Command.first) << std::endl;
            }
        }
        return true;
    }

    std::string Console::Help::Info(const std::string & Topic) const
    {
        return "Prints help for all commands\n"
            "Type help (command name) (topic) to get help on a specific command";
    }

    // History
    Console::History::History()
    {
    }

    Console::History::~History()
    {
    }

    bool Console::History::Run(const std::vector<std::string>& Arguments)
    {
        SetTextColor(Color::Info);
        for( const auto &Command : Console::Instance()->PrevCommands )
        {
            std::cout << Command << std::endl;
        }
        return true;
    }

    std::string Console::History::Info(const std::string & Topic) const
    {
        return "Displays all previously entered commands";
    }

    // Quit
    Console::Quit::Quit()
    {
    }

    Console::Quit::~Quit()
    {
    }

    bool Console::Quit::Run(const std::vector<std::string>& Arguments)
    {
        std::exit(0);
        return true;
    }

    std::string Console::Quit::Info(const std::string & Topic) const
    {
        return "Quits the application";
    }

    // Static Functions

    void SetTextColor(Color NewColor)
    {
        SetConsoleTextAttribute(
            GetStdHandle(STD_OUTPUT_HANDLE),
            static_cast<std::underlying_type_t<Color>>(NewColor)
        );
    }

    bool AllocateConsole(const std::string& ConsoleTitle)
    {
        // Allocate new console window
        if( !AllocConsole() )
        {
            MessageBox(nullptr, "Unable to allocate console", ConsoleTitle.c_str(), 0);
            return false;
        }

        CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;

        GetConsoleScreenBufferInfo(
            GetStdHandle(STD_OUTPUT_HANDLE),
            &ConsoleInfo
        );

        ConsoleInfo.dwSize.Y = 25;
        ConsoleInfo.dwSize.X = 30;

        SetConsoleScreenBufferSize(
            GetStdHandle(STD_OUTPUT_HANDLE),
            ConsoleInfo.dwSize
        );

        if( !SetConsoleTitle(ConsoleTitle.c_str()) )
        {
            MessageBox(
                nullptr,
                ("Unable set console title (Error code: " + std::to_string(GetLastError()) + ')').c_str(),
                ConsoleTitle.c_str(),
                0
            );
            return false;
        }

        if( EnableMenuItem(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE | SC_MINIMIZE, MF_GRAYED) == -1 )
        {
            MessageBox(
                nullptr,
                "Unable to enable menu item",
                ConsoleTitle.c_str(),
                0);
            return false;
        }

        if( !DrawMenuBar(GetConsoleWindow()) )
        {
            MessageBox(
                nullptr,
                ("Unable to DrawMenuBar (Error code: " + std::to_string(GetLastError()) + ')').c_str(),
                ConsoleTitle.c_str(),
                0
            );
            return false;
        }

        // Reroute std streams
        //intptr_t hStd;
        //int32_t hConsole;
        //FILE *fp;

        //// Setup std output
        //hStd = reinterpret_cast<intptr_t>(GetStdHandle(STD_OUTPUT_HANDLE));
        //hConsole = _open_osfhandle(hStd, _O_TEXT);
        //fp = _fdopen(hConsole, "w");
        //*stdout = *fp;
        //setvbuf(stdout, nullptr, _IONBF, 0);

        //// Setup std input
        //hStd = reinterpret_cast<intptr_t>(GetStdHandle(STD_INPUT_HANDLE));
        //hConsole = _open_osfhandle(hStd, _O_TEXT);
        //fp = _fdopen(hConsole, "r");
        //*stdin = *fp;
        //setvbuf(stdin, nullptr, _IONBF, 0);

        //std::ios::sync_with_stdio();

        // New stream re-route method
        // MUCH faster
        freopen("CONIN$", "r", stdin);
        freopen("CONOUT$", "w", stdout);
        freopen("CONOUT$", "w", stderr);

        std::wcout.clear();
        std::cout.clear();
        std::wcerr.clear();
        std::cerr.clear();
        std::wcin.clear();
        std::cin.clear();

        return true;
    }

    size_t GetWidth()
    {
        CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
        if( GetConsoleScreenBufferInfo(
            GetStdHandle(STD_OUTPUT_HANDLE),
            &ConsoleInfo) )
        {
            return static_cast<size_t>(ConsoleInfo.dwSize.X);
        }
        return 0;
    }
}<commit_msg>Fixed History command to enumerate supplemental arguments<commit_after>#include "Console.hpp"

#include <algorithm>
#include <sstream>

#include <Windows.h>
#include <conio.h> // _getch()
#pragma warning(disable:4996)

#include <io.h>
#include <cctype> //isgraph

#define ps1beg "\xAF["
#define ps1end "]\xAE"

// Utils
namespace
{
    std::vector<std::string> SplitString(const std::string &String, char Delimiter)
    {
        std::vector<std::string> SplitString;
        std::stringstream StringStream(String);
        std::string Token;
        while( std::getline(StringStream, Token, Delimiter) )
        {
            SplitString.push_back(Token);
        }
        return SplitString;
    }
}

namespace Console
{
    Console::Console()
    {
        ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleOutputCP(437);

        CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo{};
        if( GetConsoleScreenBufferInfo(ConsoleHandle, &ConsoleInfo) )
        {
            ConsoleWidth = ConsoleInfo.dwSize.X;
        }

        SetTextColor(Color::Info);

        PushCommand("help", std::make_shared<Help>());
        PushCommand("history", std::make_shared<History>());
        PushCommand("quit", std::make_shared<Quit>());
    }

    std::string Console::NearestCommand(const std::string & Command) const
    {
        if( !Command.empty() )
        {
            // Find closest matching command
            std::vector<std::string> Suggestions;

            for( const auto &Cmd : Commands )
            {
                if( !Command.compare(0, Command.length(), (Cmd.first), 0, Command.length()) )
                {
                    Suggestions.push_back((Cmd.first));
                }
            }

            if( Suggestions.size() )
            {
                // Return first match, for now
                return Suggestions.front();
            }
        }
        return "";
    }

    Console::~Console()
    {
        Commands.clear();
    }

    void Console::HandleInput(uint32_t KeyCode)
    {
        switch( KeyCode )
        {
        case '\r': // Enter
        {
            SetTextColor(Color::Info);
            // Clear previous suggestion
            if( !CurSuggestion.empty() )
            {
                std::cout.width(CurSuggestion.length());
                std::cout.fill(' ');
                std::cout << "";

                std::cout.width(CurSuggestion.length());
                std::cout.fill('\b');
                std::cout << "";
            }

            std::cout << ps1end << std::endl;

            std::string Command = CurCommand.substr(0, CurCommand.find_first_of(' '));

            if( !Command.empty() )
            {
                // Run command if it exists
                if( Commands.count(Command)
                    && Commands[Command] )
                {
                    if( !Commands[Command]->Run(SplitString(CurCommand, ' ')) )
                    {
                        // Error running command;
                        SetTextColor(Color::Error);
                        std::cout << "Invalid Usage: " << Command << std::endl;
                        SetTextColor(Color::Info);
                        std::cout << Commands[Command]->Info() << std::endl;
                    }
                }
                else
                {
                    SetTextColor(Color::Error);
                    std::cout << "Unknown Command: " << Command << std::endl;
                }

                // Add to history
                PrevCommands.push_back(CurCommand);
                PrevCommand = PrevCommands.end();
                CurCommand.clear();
                CurSuggestion.clear();
            }

            SetTextColor(Color::Info);
            break;
        }
        case '\t': // Tab
        {
            // Tab completion
            if( !CurSuggestion.empty() && !CurCommand.empty() )
            {
                CurCommand = CurSuggestion;
            }
            break;
        }
        case '\x16': // Ctrl + V
        {
            // Paste in clipbard
            if( OpenClipboard(nullptr) )
            {
                std::string Clipboard(reinterpret_cast<char*>(GetClipboardData(CF_TEXT)));
                CloseClipboard();
                for( const char &CurChar : Clipboard )
                {
                    HandleInput(CurChar);
                }
            }
            break;
        }
        case 0x00: // Function Keys
        case 0xE0:
        {
            uint32_t Func = _getch();
            switch( Func )
            {
            case 0x48: // Up
            {
                if( !PrevCommands.empty() )
                {
                    if( PrevCommand != PrevCommands.begin() )
                    {
                        PrevCommand--;
                    }

                    CurCommand = *PrevCommand;
                }
                break;
            }
            case 0x50: // Down
            {
                if( !PrevCommands.empty() )
                {
                    if( PrevCommand != PrevCommands.end() && PrevCommand != PrevCommands.end() - 1 )
                    {
                        PrevCommand++;
                        CurCommand = *PrevCommand;
                    }
                    else if( PrevCommand == PrevCommands.end() - 1 )
                    {
                        PrevCommand++;
                        CurCommand.clear();
                    }
                    else
                    {
                        CurCommand.clear();
                    }
                }
                break;
            }
            }
            break;
        }
        case '\b': // Backspace
        {
            if( !CurCommand.empty() )
            {
                // Remove character from current command
                CurCommand.pop_back();
                // Update Suggestion
                CurSuggestion = NearestCommand(CurCommand);
            }
            break;
        }
        default: // Every other character (alphanum and space)
        {
            if( std::isgraph(KeyCode) || std::isspace(KeyCode) )
            {
                CurCommand.push_back(static_cast<uint8_t>(KeyCode));

                // Update Suggestion
                CurSuggestion = NearestCommand(CurCommand);
            }
            break;
        }
        }
    }

    void Console::PrintLine()
    {
        SetTextColor(Color::Info);
        std::cout << '\r';
        std::cout.width(ConsoleWidth - 1);
        std::cout.fill(' ');
        std::cout << '\r' << ps1beg;
        SetTextColor(Color::Input);

        if( CurSuggestion.length() )
        {
            // Print suggestion
            SetTextColor(Color::Suggestion);
            std::cout << CurSuggestion;
            // Go back
            std::cout.width(CurSuggestion.length());
            std::cout.fill('\b');
            std::cout << "";
        }
        // Print currently typed in command
        SetTextColor(Color::Input);
        std::cout << CurCommand;
        std::cout.flush();
    }

    void Console::PushCommand(const std::string &CommandName, std::shared_ptr<Command> Command)
    {
        Commands[CommandName] = Command;
    }
    void Console::PopCommand(const std::string &CommandName)
    {
        if( Commands.count(CommandName) )
        {
            Commands.erase(CommandName);
        }
    }

    /// Meta commands

    // Help
    Console::Help::Help()
    {
    }

    Console::Help::~Help()
    {
    }

    bool Console::Help::Run(const std::vector<std::string> &Arguments)
    {
        if( Arguments.size() > 1 )
        {
            for( auto it = Arguments.cbegin() + 1; it != Arguments.cend(); ++it )
            {
                if( Console::Instance()->Commands.count(*it) )
                {
                    std::string Padded(*it);
                    Padded.resize(Console::Instance()->ConsoleWidth / 2, '\xC4');
                    SetTextColor(Color::Info);
                    std::cout << Padded << std::endl;
                    SetTextColor(Color::Info^Color::Bright);
                    std::cout << Console::Instance()->Commands[*it]->Info() << std::endl;
                }
                else
                {
                    SetTextColor(Color::Error);
                    std::cout << "Command: " << *it << " not found." << std::endl;
                }
            }
        }
        else
        {
            // Show all command info
            for( const auto &Command : Console::Instance()->Commands )
            {
                std::string Padded(Command.first);
                Padded.resize(Console::Instance()->ConsoleWidth / 2, '\xC4');
                SetTextColor(Color::Info);
                std::cout << Padded << std::endl;
                SetTextColor(Color::Info^Color::Bright);
                std::cout << Command.second->Info(Command.first) << std::endl;
            }
        }
        return true;
    }

    std::string Console::Help::Info(const std::string & Topic) const
    {
        return "Prints help for all commands\n"
            "Type help (command name) (topic) to get help on a specific command";
    }

    // History
    Console::History::History()
    {
    }

    Console::History::~History()
    {
    }

    bool Console::History::Run(const std::vector<std::string>& Arguments)
    {
        SetTextColor(Color::Info);
        for( const auto &Command : Console::Instance()->PrevCommands )
        {
            std::cout << Command << std::endl;
        }
        return true;
    }

    std::string Console::History::Info(const std::string & Topic) const
    {
        return "Displays all previously entered commands";
    }

    // Quit
    Console::Quit::Quit()
    {
    }

    Console::Quit::~Quit()
    {
    }

    bool Console::Quit::Run(const std::vector<std::string>& Arguments)
    {
        std::exit(0);
        return true;
    }

    std::string Console::Quit::Info(const std::string & Topic) const
    {
        return "Quits the application";
    }

    // Static Functions

    void SetTextColor(Color NewColor)
    {
        SetConsoleTextAttribute(
            GetStdHandle(STD_OUTPUT_HANDLE),
            static_cast<std::underlying_type_t<Color>>(NewColor)
        );
    }

    bool AllocateConsole(const std::string& ConsoleTitle)
    {
        // Allocate new console window
        if( !AllocConsole() )
        {
            MessageBox(nullptr, "Unable to allocate console", ConsoleTitle.c_str(), 0);
            return false;
        }

        CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;

        GetConsoleScreenBufferInfo(
            GetStdHandle(STD_OUTPUT_HANDLE),
            &ConsoleInfo
        );

        ConsoleInfo.dwSize.Y = 25;
        ConsoleInfo.dwSize.X = 30;

        SetConsoleScreenBufferSize(
            GetStdHandle(STD_OUTPUT_HANDLE),
            ConsoleInfo.dwSize
        );

        if( !SetConsoleTitle(ConsoleTitle.c_str()) )
        {
            MessageBox(
                nullptr,
                ("Unable set console title (Error code: " + std::to_string(GetLastError()) + ')').c_str(),
                ConsoleTitle.c_str(),
                0
            );
            return false;
        }

        if( EnableMenuItem(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE | SC_MINIMIZE, MF_GRAYED) == -1 )
        {
            MessageBox(
                nullptr,
                "Unable to enable menu item",
                ConsoleTitle.c_str(),
                0);
            return false;
        }

        if( !DrawMenuBar(GetConsoleWindow()) )
        {
            MessageBox(
                nullptr,
                ("Unable to DrawMenuBar (Error code: " + std::to_string(GetLastError()) + ')').c_str(),
                ConsoleTitle.c_str(),
                0
            );
            return false;
        }

        // Reroute std streams
        //intptr_t hStd;
        //int32_t hConsole;
        //FILE *fp;

        //// Setup std output
        //hStd = reinterpret_cast<intptr_t>(GetStdHandle(STD_OUTPUT_HANDLE));
        //hConsole = _open_osfhandle(hStd, _O_TEXT);
        //fp = _fdopen(hConsole, "w");
        //*stdout = *fp;
        //setvbuf(stdout, nullptr, _IONBF, 0);

        //// Setup std input
        //hStd = reinterpret_cast<intptr_t>(GetStdHandle(STD_INPUT_HANDLE));
        //hConsole = _open_osfhandle(hStd, _O_TEXT);
        //fp = _fdopen(hConsole, "r");
        //*stdin = *fp;
        //setvbuf(stdin, nullptr, _IONBF, 0);

        //std::ios::sync_with_stdio();

        // New stream re-route method
        // MUCH faster
        freopen("CONIN$", "r", stdin);
        freopen("CONOUT$", "w", stdout);
        freopen("CONOUT$", "w", stderr);

        std::wcout.clear();
        std::cout.clear();
        std::wcerr.clear();
        std::cerr.clear();
        std::wcin.clear();
        std::cin.clear();

        return true;
    }

    size_t GetWidth()
    {
        CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
        if( GetConsoleScreenBufferInfo(
            GetStdHandle(STD_OUTPUT_HANDLE),
            &ConsoleInfo) )
        {
            return static_cast<size_t>(ConsoleInfo.dwSize.X);
        }
        return 0;
    }
}<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// name: sig_gen.cpp
// desc: real-time sine wave
//
// author: Nikhil Goel (nmgoel@stanford.edu)
//   date: fall 2015
//   uses: RtAudio by Gary Scavone
//-----------------------------------------------------------------------------
#include "RtAudio.h"
#include <math.h>
#include <iostream>
#include <cstdlib>
using namespace std;

/* #defines and globals */

// A sample is a discrete time signal derived from a continuous signal
#define SAMPLE double

// RtAudio's data format type. Normalized between +- 1
#define MY_FORMAT RTAUDIO_FLOAT64

// Sample Rate = (avg. # of samples)/second = 1/T, where T is sampling interval
#define MY_SRATE 44100

// number of channels
#define MY_CHANNELS 2

#define MY_PIE 3.14159265358979

// global for frequency
SAMPLE g_freq = 440;

// global sample number variable
SAMPLE g_t = 0;

/*
 * @funtion audio_callback The RtAudioCallback function.
 * @param outputBuffer Pointer to the buffer that holds the output.
 * @param inputBuffer Pointer to the buffer that holds the input.
 * @param numFrames The number of sample frames held by input buffer
    and written to output buffer.
 * @param streamTime The number of seconds (double) that the signal streams.
 * @param status Notifies if there is an output/input overflow/underflow.
 * @param data Pointer to optional data provided by the client
    when opening the stream (default = NULL).
   @return Zero to maintain normal stream. One to stop the stream and drain the
   output buffer. Two to abort the stream immediately.
 */
int audio_callback(void *outputBuffer, void *inputBuffer, unsigned int numFrames,
     double streamTime, RtAudioStreamStatus status, void *data ) {

         // stderr prints info and err messages (info about callback here)
         cerr << ".";

         // outputBuffer points to array of SAMPLEs
         SAMPLE *buffer = (SAMPLE *) outputBuffer;
         for(int i = 0; i < numFrames; i++)
         {
             // generate signal in even-indexed slots of the buffer
             buffer[i * MY_CHANNELS] = sin(2 * MY_PIE * g_freq * g_t / MY_SRATE);

             // copy signal into odd-indexed slots of the buffer
             for(int j = 1; j < MY_CHANNELS; j++)
                 buffer[i * MY_CHANNELS + j] = buffer[i * MY_CHANNELS];

             // increment sample number
             g_t += 1.0;
         }
         return 0;
}

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

<<<<<<< HEAD:MyHelloSine.cpp
    RtAudio audio = new RtAudio(RtAudio::WINDOWS_ASIO);
=======
    RtAudio audio;// = new RtAudio(RtAudio::MACOSX_CORE);
>>>>>>> 6d27b44e474e41242774e452eafc836caa1d85f3:sig_gen.cpp
    unsigned int bufferBytes = 0;

    // frame size
    unsigned int bufferFrames = 512;

    // check for audio devices
    if(audio.getDeviceCount() < 1)
    {
        cout << "no audio devices found!" << endl;
        exit(1);
    }

    // let RtAudio print messages to stderr.
    //audio.showWarnings(true);

    // set input and output parameters
    RtAudio::StreamParameters iParams, oParams;
    iParams.deviceId = audio.getDefaultInputDevice();
    iParams.nChannels = MY_CHANNELS;
    iParams.firstChannel = 0;
    oParams.deviceId = audio.getDefaultOutputDevice();
    oParams.nChannels = MY_CHANNELS;
    oParams.firstChannel = 0;

    // create stream options
    RtAudio::StreamOptions options;

    try {
        // open a stream
        audio.openStream(&oParams, &iParams, MY_FORMAT, MY_SRATE, &bufferFrames,
            &audio_callback, (void *) &bufferBytes, &options);
    }
    catch(RtError& e)
    {
        cout << e.getMessage() << endl;
        exit(1);
    }

    // compute
    bufferBytes = bufferFrames * MY_CHANNELS * sizeof(SAMPLE);

    // test RtAudio functionality for reporting latency.
    cout << "stream latency: " << audio.getStreamLatency() << " frames" << endl;

    // go for it
    try {
        // start stream
        audio.startStream();

        // get input
        char input;
        std::cout << "running... press <enter> to quit (buffer frames: " << bufferFrames << ")" << endl;
        std::cin.get(input);

        // stop the stream.
        audio.stopStream();
    }
    catch(RtError& e)
    {
        // print error message
        cout << e.getMessage() << endl;
        goto cleanup;
    }

    cleanup:
        // close if open
        if(audio.isStreamOpen())
            audio.closeStream();

    return 0;
}
<commit_msg>finished noise and sine wave<commit_after>//-----------------------------------------------------------------------------
// name: sig_gen.cpp
// desc: real-time sine wave
//
// author: Nikhil Goel (nmgoel@stanford.edu)
//   date: fall 2015
//   uses: RtAudio by Gary Scavone
//-----------------------------------------------------------------------------
#include "RtAudio.h"
#include <math.h>
#include <iostream>
#include <cstdlib>
using namespace std;

/* ----------------------#defines-------------------- */

// A sample is a discrete time signal derived from a continuous signal
#define SAMPLE double

// RtAudio's data format type. Normalized between +- 1
#define MY_FORMAT RTAUDIO_FLOAT64

// Sample Rate = (avg. # of samples)/second = 1/T, where T is sampling interval
#define MY_SRATE 44100

// number of channels
#define MY_CHANNELS 2

#define MY_PIE 3.14159265358979

/* ----------------------globals--------------------- */

// global for frequency
SAMPLE g_freq = 440;

// global sample number variable
SAMPLE g_t = 0;

SAMPLE g_width = 0;

// type of signal requested by user, enumerated in function determine_signal
int g_sig = 0;

/*---------------------------------------------------- */

/*
 * @funtion audio_callback The RtAudioCallback function.
 * @param outputBuffer Pointer to the buffer that holds the output.
 * @param inputBuffer Pointer to the buffer that holds the input.
 * @param numFrames The number of sample frames held by input buffer
    and written to output buffer.
 * @param streamTime The number of seconds (double) that the signal streams.
 * @param status Notifies if there is an output/input overflow/underflow.
 * @param data Pointer to optional data provided by the client
    when opening the stream (default = NULL).
   @return Zero to maintain normal stream. One to stop the stream and drain the
   output buffer. Two to abort the stream immediately.
 */
int audio_callback(void *outputBuffer, void *inputBuffer, unsigned int numFrames,
     double streamTime, RtAudioStreamStatus status, void *data ) {

         // stderr prints info and err messages (info about callback here)
         cerr << ".";

         // outputBuffer points to array of SAMPLEs
         SAMPLE *buffer = (SAMPLE *) outputBuffer;
         for(int i = 0; i < numFrames; i++)
         {
            // generate signal in even-indexed slots of the buffer
            switch(g_sig) {
                case 1: // sine
                    buffer[i * MY_CHANNELS] = sin(2 * MY_PIE * g_freq * g_t / MY_SRATE);
                    break;
                case 2: // saw
                    break;
                case 3: // pulse
                    break;
                case 4: // noise (white noise)
                    buffer[i * MY_CHANNELS] = (rand() % 100) / 10;
                    break;
                case 5: // impulse

                    break;
                default: // any erroneous input in the type argument
                    return 2;
            }

             // copy signal into odd-indexed slots of the buffer
             for(int j = 1; j < MY_CHANNELS; j++)
                 buffer[i * MY_CHANNELS + j] = buffer[i * MY_CHANNELS];

             // increment sample number
             g_t += 1.0;
         }
         return 0;
}

/*
 * @funtion determine_signal Returns an integer based on the type of command given.
 * @param arg command given by user input
 */
int determine_signal(string arg) {

    // sine
    if (arg == "--sine") {
        return 1;
    }

    // saw
    else if (arg == "--saw"){
        return 2;
    }

    // pulse
    else if (arg == "--pulse"){
        return 3;
    }

    // noise
    else if (arg == "--noise"){
        return 4;
    }

    //impulse
    else if (arg == "--impulse") {
        return 5;
    }

    // arg is some other input not defined by this program
    else {
        return -1;
    }
}

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

    // error checking for ./sig_gen with no additional arguments
    if (argc <= 1) {
        cout << "Not enough arguments. Must give type of signal generation." << endl;
        exit(1);
    }

    // error checking for more than four arguments
    if (argc > 4) {
        cout << "Too many arguments. Only give command [type] [frequency] [width]." << endl;
        exit(1);
    }

    // determines which type of signal user wants to generate
    g_sig = determine_signal(string(argv[1]));

    // instantiate RtAudio object
    RtAudio audio;

    // frame size
    unsigned int bufferFrames = 512;
    unsigned int bufferBytes = 0;

    // check for audio devices
    if(audio.getDeviceCount() < 1)
    {
        cout << "no audio devices found!" << endl;
        exit(1);
    }

    // let RtAudio print messages to stderr.
    audio.showWarnings(true);

    // set input and output parameters
    RtAudio::StreamParameters iParams, oParams;
    iParams.deviceId = audio.getDefaultInputDevice();
    iParams.nChannels = MY_CHANNELS;
    iParams.firstChannel = 0;
    oParams.deviceId = audio.getDefaultOutputDevice();
    oParams.nChannels = MY_CHANNELS;
    oParams.firstChannel = 0;

    // create stream options
    RtAudio::StreamOptions options;

    try {
        // open a stream
        audio.openStream(&oParams, &iParams, MY_FORMAT, MY_SRATE, &bufferFrames,
            &audio_callback, (void *) &bufferBytes, &options);
    }
    catch(RtError& e)
    {
        cout << e.getMessage() << endl;
        exit(1);
    }

    // compute
    bufferBytes = bufferFrames * MY_CHANNELS * sizeof(SAMPLE);

    // test RtAudio functionality for reporting latency.
    cout << "stream latency: " << audio.getStreamLatency() << " frames" << endl;

    // go for it
    try {
        // start stream
        audio.startStream();

        // get input
        char input;
        std::cout << "running... press <enter> to quit (buffer frames: " << bufferFrames << ")" << endl;
        std::cin.get(input);

        // stop the stream.
        audio.stopStream();
    }
    catch(RtError& e)
    {
        // print error message
        cout << e.getMessage() << endl;
        goto cleanup;
    }

    cleanup:
        // close if open
        if(audio.isStreamOpen())
            audio.closeStream();

    return 0;
}
<|endoftext|>


<commit_before>//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Begeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the X86 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "X86Subtarget.h"
#include "llvm/Module.h"
#include "X86GenSubtarget.inc"
using namespace llvm;

// FIXME: temporary.
#include "llvm/Support/CommandLine.h"
namespace {
  cl::opt<bool> EnableSSE("enable-x86-sse", cl::Hidden,
                          cl::desc("Enable sse on X86"));
}

/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
/// specified arguments.  If we can't run cpuid on the host, return true.
static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
                            unsigned *rECX, unsigned *rEDX) {
#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
#if defined(__GNUC__)
  asm ("pushl\t%%ebx\n\t"
       "cpuid\n\t"
       "movl\t%%ebx, %%esi\n\t"
       "popl\t%%ebx"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(_MSC_VER)
  __asm {
    mov   eax,value
    cpuid
    mov   esi,rEAX
    mov   dword ptr [esi],eax
    mov   esi,rEBX
    mov   dword ptr [esi],ebx
    mov   esi,rECX
    mov   dword ptr [esi],ecx
    mov   esi,rEDX
    mov   dword ptr [esi],edx
  }
  return false;
#endif
#endif
  return true;
}

static const char *GetCurrentX86CPU() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  if (GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
    return "generic";
  unsigned Family  = (EAX & (0xffffffff >> (32 - 4)) << 8) >> 8; // Bits 8 - 11
  unsigned Model   = (EAX & (0xffffffff >> (32 - 4)) << 4) >> 4; // Bits 4 - 7
  GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
  bool Em64T = EDX & (1 << 29);

  unsigned text[12];
  GetCpuIDAndInfo(0x80000002, text+0, text+1, text+2, text+3);
  GetCpuIDAndInfo(0x80000003, text+4, text+5, text+6, text+7);
  GetCpuIDAndInfo(0x80000004, text+8, text+9, text+10, text+11);
  char *t = reinterpret_cast<char *>(&text[0]);
  while (*t == ' ')
	  t++;

  if (memcmp(t, "Intel", 5) == 0) {
    switch (Family) {
      case 3:
        return "i386";
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 4:  return "pentium-mmx";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 1:  return "pentiumpro";
        case 3:
        case 5:
        case 6:  return "pentium2";
        case 7:
        case 8:
        case 10:
        case 11: return "pentium3";
        case 9:
        case 13: return "pentium-m";
        case 14: return "yonah";
        default: return "i686";
        }
      case 15: {
        switch (Model) {
        case 3:
        case 4:
          return (Em64T) ? "nocona" : "prescott";
        default:
          return (Em64T) ? "x86-64" : "pentium4";
        }
      }

    default:
      return "generic";
    }
  } else if (memcmp(t, "AMD", 3) == 0) {
    // FIXME: fill in remaining family/model combinations
    switch (Family) {
      case 15:
        return (Em64T) ? "athlon64" : "athlon";

    default:
      return "generic";
    }
  } else {
    return "generic";
  }
}

X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) {
  stackAlignment = 8;
  indirectExternAndWeakGlobals = false;
  X86SSELevel = NoMMXSSE;
  X863DNowLevel = NoThreeDNow;
  Is64Bit = false;

  // Determine default and user specified characteristics
  std::string CPU = GetCurrentX86CPU();

  // Parse features string.
  ParseSubtargetFeatures(FS, CPU);

  // Default to ELF unless otherwise specified.
  TargetType = isELF;

  // FIXME: Force these off until they work.  An llc-beta option should turn
  // them back on.
  if (!EnableSSE) {
    X86SSELevel = NoMMXSSE;
    X863DNowLevel = NoThreeDNow;
  }

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    if (TT.find("cygwin") != std::string::npos ||
        TT.find("mingw")  != std::string::npos)
      TargetType = isCygwin;
    else if (TT.find("darwin") != std::string::npos)
      TargetType = isDarwin;
    else if (TT.find("win32") != std::string::npos)
      TargetType = isWindows;
  } else if (TT.empty()) {
#if defined(__CYGWIN__) || defined(__MINGW32__)
    TargetType = isCygwin;
#elif defined(__APPLE__)
    TargetType = isDarwin;
#elif defined(_WIN32)
    TargetType = isWindows;
#endif
  }

  if (TargetType == isDarwin) {
    stackAlignment = 16;
    indirectExternAndWeakGlobals = true;
  }
}
<commit_msg>Use union instead of reinterpret_cast.<commit_after>//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Begeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the X86 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "X86Subtarget.h"
#include "llvm/Module.h"
#include "X86GenSubtarget.inc"
using namespace llvm;

// FIXME: temporary.
#include "llvm/Support/CommandLine.h"
namespace {
  cl::opt<bool> EnableSSE("enable-x86-sse", cl::Hidden,
                          cl::desc("Enable sse on X86"));
}

/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
/// specified arguments.  If we can't run cpuid on the host, return true.
static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
                            unsigned *rECX, unsigned *rEDX) {
#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
#if defined(__GNUC__)
  asm ("pushl\t%%ebx\n\t"
       "cpuid\n\t"
       "movl\t%%ebx, %%esi\n\t"
       "popl\t%%ebx"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(_MSC_VER)
  __asm {
    mov   eax,value
    cpuid
    mov   esi,rEAX
    mov   dword ptr [esi],eax
    mov   esi,rEBX
    mov   dword ptr [esi],ebx
    mov   esi,rECX
    mov   dword ptr [esi],ecx
    mov   esi,rEDX
    mov   dword ptr [esi],edx
  }
  return false;
#endif
#endif
  return true;
}

static const char *GetCurrentX86CPU() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  if (GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
    return "generic";
  unsigned Family  = (EAX & (0xffffffff >> (32 - 4)) << 8) >> 8; // Bits 8 - 11
  unsigned Model   = (EAX & (0xffffffff >> (32 - 4)) << 4) >> 4; // Bits 4 - 7
  GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
  bool Em64T = EDX & (1 << 29);

  union {
    unsigned u[12];
    char     c[48];
  } text;

  GetCpuIDAndInfo(0x80000002, text.u+0, text.u+1, text.u+2, text.u+3);
  GetCpuIDAndInfo(0x80000003, text.u+4, text.u+5, text.u+6, text.u+7);
  GetCpuIDAndInfo(0x80000004, text.u+8, text.u+9, text.u+10, text.u+11);
  char *t = text.c;
  while (*t == ' ')
	  t++;

  if (memcmp(t, "Intel", 5) == 0) {
    switch (Family) {
      case 3:
        return "i386";
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 4:  return "pentium-mmx";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 1:  return "pentiumpro";
        case 3:
        case 5:
        case 6:  return "pentium2";
        case 7:
        case 8:
        case 10:
        case 11: return "pentium3";
        case 9:
        case 13: return "pentium-m";
        case 14: return "yonah";
        default: return "i686";
        }
      case 15: {
        switch (Model) {
        case 3:
        case 4:
          return (Em64T) ? "nocona" : "prescott";
        default:
          return (Em64T) ? "x86-64" : "pentium4";
        }
      }

    default:
      return "generic";
    }
  } else if (memcmp(t, "AMD", 3) == 0) {
    // FIXME: fill in remaining family/model combinations
    switch (Family) {
      case 15:
        return (Em64T) ? "athlon64" : "athlon";

    default:
      return "generic";
    }
  } else {
    return "generic";
  }
}

X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) {
  stackAlignment = 8;
  indirectExternAndWeakGlobals = false;
  X86SSELevel = NoMMXSSE;
  X863DNowLevel = NoThreeDNow;
  Is64Bit = false;

  // Determine default and user specified characteristics
  std::string CPU = GetCurrentX86CPU();

  // Parse features string.
  ParseSubtargetFeatures(FS, CPU);

  // Default to ELF unless otherwise specified.
  TargetType = isELF;

  // FIXME: Force these off until they work.  An llc-beta option should turn
  // them back on.
  if (!EnableSSE) {
    X86SSELevel = NoMMXSSE;
    X863DNowLevel = NoThreeDNow;
  }

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    if (TT.find("cygwin") != std::string::npos ||
        TT.find("mingw")  != std::string::npos)
      TargetType = isCygwin;
    else if (TT.find("darwin") != std::string::npos)
      TargetType = isDarwin;
    else if (TT.find("win32") != std::string::npos)
      TargetType = isWindows;
  } else if (TT.empty()) {
#if defined(__CYGWIN__) || defined(__MINGW32__)
    TargetType = isCygwin;
#elif defined(__APPLE__)
    TargetType = isDarwin;
#elif defined(_WIN32)
    TargetType = isWindows;
#endif
  }

  if (TargetType == isDarwin) {
    stackAlignment = 16;
    indirectExternAndWeakGlobals = true;
  }
}
<|endoftext|>