<commit_before>//===- MachOObject.cpp - Mach-O Object File Wrapper -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/MachOObject.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SwapByteOrder.h"

using namespace llvm;
using namespace llvm::object;

/* Translation Utilities */

template<typename T>
static void SwapValue(T &Value) {
  Value = sys::SwapByteOrder(Value);
}

template<typename T>
static void SwapStruct(T &Value);

template<typename T>
static void ReadInMemoryStruct(const MachOObject &MOO,
                               StringRef Buffer, uint64_t Base,
                               InMemoryStruct<T> &Res) {
  typedef T struct_type;
  uint64_t Size = sizeof(struct_type);

  // Check that the buffer contains the expected data.
  if (Base + Size >  Buffer.size()) {
    Res = 0;
    return;
  }

  // Check whether we can return a direct pointer.
  struct_type *Ptr = (struct_type *) (Buffer.data() + Base);
  if (!MOO.isSwappedEndian()) {
    Res = Ptr;
    return;
  }

  // Otherwise, copy the struct and translate the values.
  Res = *Ptr;
  SwapStruct(*Res);
}

/* *** */

MachOObject::MachOObject(MemoryBuffer *Buffer_, bool IsLittleEndian_,
                         bool Is64Bit_)
  : Buffer(Buffer_), IsLittleEndian(IsLittleEndian_), Is64Bit(Is64Bit_),
    IsSwappedEndian(IsLittleEndian != sys::isLittleEndianHost()),
    HasStringTable(false), LoadCommands(0), NumLoadedCommands(0) {
  // Load the common header.
  memcpy(&Header, Buffer->getBuffer().data(), sizeof(Header));
  if (IsSwappedEndian) {
    SwapValue(Header.Magic);
    SwapValue(Header.CPUType);
    SwapValue(Header.CPUSubtype);
    SwapValue(Header.FileType);
    SwapValue(Header.NumLoadCommands);
    SwapValue(Header.SizeOfLoadCommands);
    SwapValue(Header.Flags);
  }

  if (is64Bit()) {
    memcpy(&Header64Ext, Buffer->getBuffer().data() + sizeof(Header),
           sizeof(Header64Ext));
    if (IsSwappedEndian) {
      SwapValue(Header64Ext.Reserved);
    }
  }

  // Create the load command array if sane.
  if (getHeader().NumLoadCommands < (1 << 20))
    LoadCommands = new LoadCommandInfo[getHeader().NumLoadCommands];
}

MachOObject::~MachOObject() {
  delete [] LoadCommands;
}

MachOObject *MachOObject::LoadFromBuffer(MemoryBuffer *Buffer,
                                         std::string *ErrorStr) {
  // First, check the magic value and initialize the basic object info.
  bool IsLittleEndian = false, Is64Bit = false;
  StringRef Magic = Buffer->getBuffer().slice(0, 4);
  if (Magic == "\xFE\xED\xFA\xCE") {
  }  else if (Magic == "\xCE\xFA\xED\xFE") {
    IsLittleEndian = true;
  } else if (Magic == "\xFE\xED\xFA\xCF") {
    Is64Bit = true;
  } else if (Magic == "\xCF\xFA\xED\xFE") {
    IsLittleEndian = true;
    Is64Bit = true;
  } else {
    if (ErrorStr) *ErrorStr = "not a Mach object file (invalid magic)";
    return 0;
  }

  // Ensure that the at least the full header is present.
  unsigned HeaderSize = Is64Bit ? macho::Header64Size : macho::Header32Size;
  if (Buffer->getBufferSize() < HeaderSize) {
    if (ErrorStr) *ErrorStr = "not a Mach object file (invalid header)";
    return 0;
  }

  OwningPtr<MachOObject> Object(new MachOObject(Buffer, IsLittleEndian,
                                                Is64Bit));

  // Check for bogus number of load commands.
  if (Object->getHeader().NumLoadCommands >= (1 << 20)) {
    if (ErrorStr) *ErrorStr = "not a Mach object file (unreasonable header)";
    return 0;
  }

  if (ErrorStr) *ErrorStr = "";
  return Object.take();
}

StringRef MachOObject::getData(size_t Offset, size_t Size) const {
  return Buffer->getBuffer().substr(Offset,Size);
}

void MachOObject::RegisterStringTable(macho::SymtabLoadCommand &SLC) {
  HasStringTable = true;
  StringTable = Buffer->getBuffer().substr(SLC.StringTableOffset,
                                           SLC.StringTableSize);
}

const MachOObject::LoadCommandInfo &
MachOObject::getLoadCommandInfo(unsigned Index) const {
  assert(Index < getHeader().NumLoadCommands && "Invalid index!");

  // Load the command, if necessary.
  if (Index >= NumLoadedCommands) {
    uint64_t Offset;
    if (Index == 0) {
      Offset = getHeaderSize();
    } else {
      const LoadCommandInfo &Prev = getLoadCommandInfo(Index - 1);
      Offset = Prev.Offset + Prev.Command.Size;
    }

    LoadCommandInfo &Info = LoadCommands[Index];
    memcpy(&Info.Command, Buffer->getBuffer().data() + Offset,
           sizeof(macho::LoadCommand));
    if (IsSwappedEndian) {
      SwapValue(Info.Command.Type);
      SwapValue(Info.Command.Size);
    }
    Info.Offset = Offset;
    NumLoadedCommands = Index + 1;
  }

  return LoadCommands[Index];
}

template<>
void SwapStruct(macho::SegmentLoadCommand &Value) {
  SwapValue(Value.Type);
  SwapValue(Value.Size);
  SwapValue(Value.VMAddress);
  SwapValue(Value.VMSize);
  SwapValue(Value.FileOffset);
  SwapValue(Value.FileSize);
  SwapValue(Value.MaxVMProtection);
  SwapValue(Value.InitialVMProtection);
  SwapValue(Value.NumSections);
  SwapValue(Value.Flags);
}
void MachOObject::ReadSegmentLoadCommand(const LoadCommandInfo &LCI,
                         InMemoryStruct<macho::SegmentLoadCommand> &Res) const {
  ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
}

template<>
void SwapStruct(macho::Segment64LoadCommand &Value) {
  SwapValue(Value.Type);
  SwapValue(Value.Size);
  SwapValue(Value.VMAddress);
  SwapValue(Value.VMSize);
  SwapValue(Value.FileOffset);
  SwapValue(Value.FileSize);
  SwapValue(Value.MaxVMProtection);
  SwapValue(Value.InitialVMProtection);
  SwapValue(Value.NumSections);
  SwapValue(Value.Flags);
}
void MachOObject::ReadSegment64LoadCommand(const LoadCommandInfo &LCI,
                       InMemoryStruct<macho::Segment64LoadCommand> &Res) const {
  ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
}

template<>
void SwapStruct(macho::SymtabLoadCommand &Value) {
  SwapValue(Value.Type);
  SwapValue(Value.Size);
  SwapValue(Value.SymbolTableOffset);
  SwapValue(Value.NumSymbolTableEntries);
  SwapValue(Value.StringTableOffset);
  SwapValue(Value.StringTableSize);
}
void MachOObject::ReadSymtabLoadCommand(const LoadCommandInfo &LCI,
                          InMemoryStruct<macho::SymtabLoadCommand> &Res) const {
  ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
}

template<>
void SwapStruct(macho::DysymtabLoadCommand &Value) {
  SwapValue(Value.Type);
  SwapValue(Value.Size);
  SwapValue(Value.LocalSymbolsIndex);
  SwapValue(Value.NumLocalSymbols);
  SwapValue(Value.ExternalSymbolsIndex);
  SwapValue(Value.NumExternalSymbols);
  SwapValue(Value.UndefinedSymbolsIndex);
  SwapValue(Value.NumUndefinedSymbols);
  SwapValue(Value.TOCOffset);
  SwapValue(Value.NumTOCEntries);
  SwapValue(Value.ModuleTableOffset);
  SwapValue(Value.NumModuleTableEntries);
  SwapValue(Value.ReferenceSymbolTableOffset);
  SwapValue(Value.NumReferencedSymbolTableEntries);
  SwapValue(Value.IndirectSymbolTableOffset);
  SwapValue(Value.NumIndirectSymbolTableEntries);
  SwapValue(Value.ExternalRelocationTableOffset);
  SwapValue(Value.NumExternalRelocationTableEntries);
  SwapValue(Value.LocalRelocationTableOffset);
  SwapValue(Value.NumLocalRelocationTableEntries);
}
void MachOObject::ReadDysymtabLoadCommand(const LoadCommandInfo &LCI,
                        InMemoryStruct<macho::DysymtabLoadCommand> &Res) const {
  ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
}

template<>
void SwapStruct(macho::LinkeditDataLoadCommand &Value) {
  SwapValue(Value.Type);
  SwapValue(Value.Size);
  SwapValue(Value.DataOffset);
  SwapValue(Value.DataSize);
}
void MachOObject::ReadLinkeditDataLoadCommand(const LoadCommandInfo &LCI,
                    InMemoryStruct<macho::LinkeditDataLoadCommand> &Res) const {
  ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
}

template<>
void SwapStruct(macho::IndirectSymbolTableEntry &Value) {
  SwapValue(Value.Index);
}
void
MachOObject::ReadIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC,
                                          unsigned Index,
                   InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const {
  uint64_t Offset = (DLC.IndirectSymbolTableOffset +
                     Index * sizeof(macho::IndirectSymbolTableEntry));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::Section &Value) {
  SwapValue(Value.Address);
  SwapValue(Value.Size);
  SwapValue(Value.Offset);
  SwapValue(Value.Align);
  SwapValue(Value.RelocationTableOffset);
  SwapValue(Value.NumRelocationTableEntries);
  SwapValue(Value.Flags);
  SwapValue(Value.Reserved1);
  SwapValue(Value.Reserved2);
}
void MachOObject::ReadSection(const LoadCommandInfo &LCI,
                              unsigned Index,
                              InMemoryStruct<macho::Section> &Res) const {
  assert(LCI.Command.Type == macho::LCT_Segment &&
         "Unexpected load command info!");
  uint64_t Offset = (LCI.Offset + sizeof(macho::SegmentLoadCommand) +
                     Index * sizeof(macho::Section));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::Section64 &Value) {
  SwapValue(Value.Address);
  SwapValue(Value.Size);
  SwapValue(Value.Offset);
  SwapValue(Value.Align);
  SwapValue(Value.RelocationTableOffset);
  SwapValue(Value.NumRelocationTableEntries);
  SwapValue(Value.Flags);
  SwapValue(Value.Reserved1);
  SwapValue(Value.Reserved2);
  SwapValue(Value.Reserved3);
}
void MachOObject::ReadSection64(const LoadCommandInfo &LCI,
                                unsigned Index,
                                InMemoryStruct<macho::Section64> &Res) const {
  assert(LCI.Command.Type == macho::LCT_Segment64 &&
         "Unexpected load command info!");
  uint64_t Offset = (LCI.Offset + sizeof(macho::Segment64LoadCommand) +
                     Index * sizeof(macho::Section64));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::RelocationEntry &Value) {
  SwapValue(Value.Word0);
  SwapValue(Value.Word1);
}
void MachOObject::ReadRelocationEntry(uint64_t RelocationTableOffset,
                                      unsigned Index,
                            InMemoryStruct<macho::RelocationEntry> &Res) const {
  uint64_t Offset = (RelocationTableOffset +
                     Index * sizeof(macho::RelocationEntry));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::SymbolTableEntry &Value) {
  SwapValue(Value.StringIndex);
  SwapValue(Value.Flags);
  SwapValue(Value.Value);
}
void MachOObject::ReadSymbolTableEntry(uint64_t SymbolTableOffset,
                                       unsigned Index,
                           InMemoryStruct<macho::SymbolTableEntry> &Res) const {
  uint64_t Offset = (SymbolTableOffset +
                     Index * sizeof(macho::SymbolTableEntry));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::Symbol64TableEntry &Value) {
  SwapValue(Value.StringIndex);
  SwapValue(Value.Flags);
  SwapValue(Value.Value);
}
void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset,
                                       unsigned Index,
                         InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
  uint64_t Offset = (SymbolTableOffset +
                     Index * sizeof(macho::Symbol64TableEntry));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::DataInCodeTableEntry &Value) {
  SwapValue(Value.Offset);
  SwapValue(Value.Length);
  SwapValue(Value.Kind);
}
void MachOObject::ReadDataInCodeTableEntry(uint64_t TableOffset,
                                           unsigned Index,
                       InMemoryStruct<macho::DataInCodeTableEntry> &Res) const {
  uint64_t Offset = (TableOffset +
                     Index * sizeof(macho::DataInCodeTableEntry));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

void MachOObject::ReadULEB128s(uint64_t Index,
                               SmallVectorImpl<uint64_t> &Out) const {
  DataExtractor extractor(Buffer->getBuffer(), true, 0);

  uint32_t offset = Index;
  uint64_t data = 0;
  while (uint64_t delta = extractor.getULEB128(&offset)) {
    data += delta;
    Out.push_back(data);
  }
}

/* ** */
// Object Dumping Facilities
void MachOObject::dump() const { print(dbgs()); dbgs() << '\n'; }
void MachOObject::dumpHeader() const { printHeader(dbgs()); dbgs() << '\n'; }

void MachOObject::printHeader(raw_ostream &O) const {
  O << "('cputype', " << Header.CPUType << ")\n";
  O << "('cpusubtype', " << Header.CPUSubtype << ")\n";
  O << "('filetype', " << Header.FileType << ")\n";
  O << "('num_load_commands', " << Header.NumLoadCommands << ")\n";
  O << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n";
  O << "('flag', " << Header.Flags << ")\n";

  // Print extended header if 64-bit.
  if (is64Bit())
    O << "('reserved', " << Header64Ext.Reserved << ")\n";
}

void MachOObject::print(raw_ostream &O) const {
  O << "Header:\n";
  printHeader(O);
  O << "Load Commands:\n";

  O << "Buffer:\n";
}
<commit_msg>Fixed few warnings.<commit_after>//===- MachOObject.cpp - Mach-O Object File Wrapper -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/MachOObject.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SwapByteOrder.h"

using namespace llvm;
using namespace llvm::object;

/* Translation Utilities */

template<typename T>
static void SwapValue(T &Value) {
  Value = sys::SwapByteOrder(Value);
}

template<typename T>
static void SwapStruct(T &Value);

template<typename T>
static void ReadInMemoryStruct(const MachOObject &MOO,
                               StringRef Buffer, uint64_t Base,
                               InMemoryStruct<T> &Res) {
  typedef T struct_type;
  uint64_t Size = sizeof(struct_type);

  // Check that the buffer contains the expected data.
  if (Base + Size >  Buffer.size()) {
    Res = 0;
    return;
  }

  // Check whether we can return a direct pointer.
  struct_type *Ptr =
    const_cast<struct_type *>((const struct_type *)(Buffer.data() + Base));
  if (!MOO.isSwappedEndian()) {
    Res = Ptr;
    return;
  }

  // Otherwise, copy the struct and translate the values.
  Res = *Ptr;
  SwapStruct(*Res);
}

/* *** */

MachOObject::MachOObject(MemoryBuffer *Buffer_, bool IsLittleEndian_,
                         bool Is64Bit_)
  : Buffer(Buffer_), IsLittleEndian(IsLittleEndian_), Is64Bit(Is64Bit_),
    IsSwappedEndian(IsLittleEndian != sys::isLittleEndianHost()),
    HasStringTable(false), LoadCommands(0), NumLoadedCommands(0) {
  // Load the common header.
  memcpy(&Header, Buffer->getBuffer().data(), sizeof(Header));
  if (IsSwappedEndian) {
    SwapValue(Header.Magic);
    SwapValue(Header.CPUType);
    SwapValue(Header.CPUSubtype);
    SwapValue(Header.FileType);
    SwapValue(Header.NumLoadCommands);
    SwapValue(Header.SizeOfLoadCommands);
    SwapValue(Header.Flags);
  }

  if (is64Bit()) {
    memcpy(&Header64Ext, Buffer->getBuffer().data() + sizeof(Header),
           sizeof(Header64Ext));
    if (IsSwappedEndian) {
      SwapValue(Header64Ext.Reserved);
    }
  }

  // Create the load command array if sane.
  if (getHeader().NumLoadCommands < (1 << 20))
    LoadCommands = new LoadCommandInfo[getHeader().NumLoadCommands];
}

MachOObject::~MachOObject() {
  delete [] LoadCommands;
}

MachOObject *MachOObject::LoadFromBuffer(MemoryBuffer *Buffer,
                                         std::string *ErrorStr) {
  // First, check the magic value and initialize the basic object info.
  bool IsLittleEndian = false, Is64Bit = false;
  StringRef Magic = Buffer->getBuffer().slice(0, 4);
  if (Magic == "\xFE\xED\xFA\xCE") {
  }  else if (Magic == "\xCE\xFA\xED\xFE") {
    IsLittleEndian = true;
  } else if (Magic == "\xFE\xED\xFA\xCF") {
    Is64Bit = true;
  } else if (Magic == "\xCF\xFA\xED\xFE") {
    IsLittleEndian = true;
    Is64Bit = true;
  } else {
    if (ErrorStr) *ErrorStr = "not a Mach object file (invalid magic)";
    return 0;
  }

  // Ensure that the at least the full header is present.
  unsigned HeaderSize = Is64Bit ? macho::Header64Size : macho::Header32Size;
  if (Buffer->getBufferSize() < HeaderSize) {
    if (ErrorStr) *ErrorStr = "not a Mach object file (invalid header)";
    return 0;
  }

  OwningPtr<MachOObject> Object(new MachOObject(Buffer, IsLittleEndian,
                                                Is64Bit));

  // Check for bogus number of load commands.
  if (Object->getHeader().NumLoadCommands >= (1 << 20)) {
    if (ErrorStr) *ErrorStr = "not a Mach object file (unreasonable header)";
    return 0;
  }

  if (ErrorStr) *ErrorStr = "";
  return Object.take();
}

StringRef MachOObject::getData(size_t Offset, size_t Size) const {
  return Buffer->getBuffer().substr(Offset,Size);
}

void MachOObject::RegisterStringTable(macho::SymtabLoadCommand &SLC) {
  HasStringTable = true;
  StringTable = Buffer->getBuffer().substr(SLC.StringTableOffset,
                                           SLC.StringTableSize);
}

const MachOObject::LoadCommandInfo &
MachOObject::getLoadCommandInfo(unsigned Index) const {
  assert(Index < getHeader().NumLoadCommands && "Invalid index!");

  // Load the command, if necessary.
  if (Index >= NumLoadedCommands) {
    uint64_t Offset;
    if (Index == 0) {
      Offset = getHeaderSize();
    } else {
      const LoadCommandInfo &Prev = getLoadCommandInfo(Index - 1);
      Offset = Prev.Offset + Prev.Command.Size;
    }

    LoadCommandInfo &Info = LoadCommands[Index];
    memcpy(&Info.Command, Buffer->getBuffer().data() + Offset,
           sizeof(macho::LoadCommand));
    if (IsSwappedEndian) {
      SwapValue(Info.Command.Type);
      SwapValue(Info.Command.Size);
    }
    Info.Offset = Offset;
    NumLoadedCommands = Index + 1;
  }

  return LoadCommands[Index];
}

template<>
void SwapStruct(macho::SegmentLoadCommand &Value) {
  SwapValue(Value.Type);
  SwapValue(Value.Size);
  SwapValue(Value.VMAddress);
  SwapValue(Value.VMSize);
  SwapValue(Value.FileOffset);
  SwapValue(Value.FileSize);
  SwapValue(Value.MaxVMProtection);
  SwapValue(Value.InitialVMProtection);
  SwapValue(Value.NumSections);
  SwapValue(Value.Flags);
}
void MachOObject::ReadSegmentLoadCommand(const LoadCommandInfo &LCI,
                         InMemoryStruct<macho::SegmentLoadCommand> &Res) const {
  ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
}

template<>
void SwapStruct(macho::Segment64LoadCommand &Value) {
  SwapValue(Value.Type);
  SwapValue(Value.Size);
  SwapValue(Value.VMAddress);
  SwapValue(Value.VMSize);
  SwapValue(Value.FileOffset);
  SwapValue(Value.FileSize);
  SwapValue(Value.MaxVMProtection);
  SwapValue(Value.InitialVMProtection);
  SwapValue(Value.NumSections);
  SwapValue(Value.Flags);
}
void MachOObject::ReadSegment64LoadCommand(const LoadCommandInfo &LCI,
                       InMemoryStruct<macho::Segment64LoadCommand> &Res) const {
  ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
}

template<>
void SwapStruct(macho::SymtabLoadCommand &Value) {
  SwapValue(Value.Type);
  SwapValue(Value.Size);
  SwapValue(Value.SymbolTableOffset);
  SwapValue(Value.NumSymbolTableEntries);
  SwapValue(Value.StringTableOffset);
  SwapValue(Value.StringTableSize);
}
void MachOObject::ReadSymtabLoadCommand(const LoadCommandInfo &LCI,
                          InMemoryStruct<macho::SymtabLoadCommand> &Res) const {
  ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
}

template<>
void SwapStruct(macho::DysymtabLoadCommand &Value) {
  SwapValue(Value.Type);
  SwapValue(Value.Size);
  SwapValue(Value.LocalSymbolsIndex);
  SwapValue(Value.NumLocalSymbols);
  SwapValue(Value.ExternalSymbolsIndex);
  SwapValue(Value.NumExternalSymbols);
  SwapValue(Value.UndefinedSymbolsIndex);
  SwapValue(Value.NumUndefinedSymbols);
  SwapValue(Value.TOCOffset);
  SwapValue(Value.NumTOCEntries);
  SwapValue(Value.ModuleTableOffset);
  SwapValue(Value.NumModuleTableEntries);
  SwapValue(Value.ReferenceSymbolTableOffset);
  SwapValue(Value.NumReferencedSymbolTableEntries);
  SwapValue(Value.IndirectSymbolTableOffset);
  SwapValue(Value.NumIndirectSymbolTableEntries);
  SwapValue(Value.ExternalRelocationTableOffset);
  SwapValue(Value.NumExternalRelocationTableEntries);
  SwapValue(Value.LocalRelocationTableOffset);
  SwapValue(Value.NumLocalRelocationTableEntries);
}
void MachOObject::ReadDysymtabLoadCommand(const LoadCommandInfo &LCI,
                        InMemoryStruct<macho::DysymtabLoadCommand> &Res) const {
  ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
}

template<>
void SwapStruct(macho::LinkeditDataLoadCommand &Value) {
  SwapValue(Value.Type);
  SwapValue(Value.Size);
  SwapValue(Value.DataOffset);
  SwapValue(Value.DataSize);
}
void MachOObject::ReadLinkeditDataLoadCommand(const LoadCommandInfo &LCI,
                    InMemoryStruct<macho::LinkeditDataLoadCommand> &Res) const {
  ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
}

template<>
void SwapStruct(macho::IndirectSymbolTableEntry &Value) {
  SwapValue(Value.Index);
}
void
MachOObject::ReadIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC,
                                          unsigned Index,
                   InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const {
  uint64_t Offset = (DLC.IndirectSymbolTableOffset +
                     Index * sizeof(macho::IndirectSymbolTableEntry));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::Section &Value) {
  SwapValue(Value.Address);
  SwapValue(Value.Size);
  SwapValue(Value.Offset);
  SwapValue(Value.Align);
  SwapValue(Value.RelocationTableOffset);
  SwapValue(Value.NumRelocationTableEntries);
  SwapValue(Value.Flags);
  SwapValue(Value.Reserved1);
  SwapValue(Value.Reserved2);
}
void MachOObject::ReadSection(const LoadCommandInfo &LCI,
                              unsigned Index,
                              InMemoryStruct<macho::Section> &Res) const {
  assert(LCI.Command.Type == macho::LCT_Segment &&
         "Unexpected load command info!");
  uint64_t Offset = (LCI.Offset + sizeof(macho::SegmentLoadCommand) +
                     Index * sizeof(macho::Section));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::Section64 &Value) {
  SwapValue(Value.Address);
  SwapValue(Value.Size);
  SwapValue(Value.Offset);
  SwapValue(Value.Align);
  SwapValue(Value.RelocationTableOffset);
  SwapValue(Value.NumRelocationTableEntries);
  SwapValue(Value.Flags);
  SwapValue(Value.Reserved1);
  SwapValue(Value.Reserved2);
  SwapValue(Value.Reserved3);
}
void MachOObject::ReadSection64(const LoadCommandInfo &LCI,
                                unsigned Index,
                                InMemoryStruct<macho::Section64> &Res) const {
  assert(LCI.Command.Type == macho::LCT_Segment64 &&
         "Unexpected load command info!");
  uint64_t Offset = (LCI.Offset + sizeof(macho::Segment64LoadCommand) +
                     Index * sizeof(macho::Section64));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::RelocationEntry &Value) {
  SwapValue(Value.Word0);
  SwapValue(Value.Word1);
}
void MachOObject::ReadRelocationEntry(uint64_t RelocationTableOffset,
                                      unsigned Index,
                            InMemoryStruct<macho::RelocationEntry> &Res) const {
  uint64_t Offset = (RelocationTableOffset +
                     Index * sizeof(macho::RelocationEntry));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::SymbolTableEntry &Value) {
  SwapValue(Value.StringIndex);
  SwapValue(Value.Flags);
  SwapValue(Value.Value);
}
void MachOObject::ReadSymbolTableEntry(uint64_t SymbolTableOffset,
                                       unsigned Index,
                           InMemoryStruct<macho::SymbolTableEntry> &Res) const {
  uint64_t Offset = (SymbolTableOffset +
                     Index * sizeof(macho::SymbolTableEntry));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::Symbol64TableEntry &Value) {
  SwapValue(Value.StringIndex);
  SwapValue(Value.Flags);
  SwapValue(Value.Value);
}
void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset,
                                       unsigned Index,
                         InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
  uint64_t Offset = (SymbolTableOffset +
                     Index * sizeof(macho::Symbol64TableEntry));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

template<>
void SwapStruct(macho::DataInCodeTableEntry &Value) {
  SwapValue(Value.Offset);
  SwapValue(Value.Length);
  SwapValue(Value.Kind);
}
void MachOObject::ReadDataInCodeTableEntry(uint64_t TableOffset,
                                           unsigned Index,
                       InMemoryStruct<macho::DataInCodeTableEntry> &Res) const {
  uint64_t Offset = (TableOffset +
                     Index * sizeof(macho::DataInCodeTableEntry));
  ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
}

void MachOObject::ReadULEB128s(uint64_t Index,
                               SmallVectorImpl<uint64_t> &Out) const {
  DataExtractor extractor(Buffer->getBuffer(), true, 0);

  uint32_t offset = Index;
  uint64_t data = 0;
  while (uint64_t delta = extractor.getULEB128(&offset)) {
    data += delta;
    Out.push_back(data);
  }
}

/* ** */
// Object Dumping Facilities
void MachOObject::dump() const { print(dbgs()); dbgs() << '\n'; }
void MachOObject::dumpHeader() const { printHeader(dbgs()); dbgs() << '\n'; }

void MachOObject::printHeader(raw_ostream &O) const {
  O << "('cputype', " << Header.CPUType << ")\n";
  O << "('cpusubtype', " << Header.CPUSubtype << ")\n";
  O << "('filetype', " << Header.FileType << ")\n";
  O << "('num_load_commands', " << Header.NumLoadCommands << ")\n";
  O << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n";
  O << "('flag', " << Header.Flags << ")\n";

  // Print extended header if 64-bit.
  if (is64Bit())
    O << "('reserved', " << Header64Ext.Reserved << ")\n";
}

void MachOObject::print(raw_ostream &O) const {
  O << "Header:\n";
  printHeader(O);
  O << "Load Commands:\n";

  O << "Buffer:\n";
}
<|endoftext|>


<commit_before>#include <ArrayInfo.hpp>
#include <numeric>
#include <algorithm>
#include <functional>

using af::dim4;
using std::partial_sum;
using std::accumulate;
using std::transform;

dim_type
calcOffset(const af::dim4 &strides, const af::dim4 &offsets)
{
    dim_type offset = 0;
    for (int i = 0; i < 4; i++) offset += offsets[i] * strides[i];
    return offset;
}

const ArrayInfo&
getInfo(af_array arr)
{
    const ArrayInfo *info = static_cast<ArrayInfo*>(reinterpret_cast<void *>(arr));
    return *info;
}

af_err
af_get_elements(dim_type *elems, const af_array arr)
{
    *elems =  getInfo(arr).elements();
    return AF_SUCCESS; //FIXME: Catch exceptions correctly
}

af_err af_get_type(af_dtype *type, const af_array arr)
{
    *type = getInfo(arr).getType();
    return AF_SUCCESS; //FIXME: Catch exceptions correctly
}

dim4 calcStrides(const dim4 &parentDim)
{
    dim4 out(1, 1, 1, 1);
    const dim_type *parentPtr = parentDim.get();
    partial_sum(parentPtr, parentPtr + parentDim.ndims(), out.get() + 1, std::multiplies<dim_type>());
    return out;
}

void ArrayInfo::modStrides(const dim4 &newStrides)
{
    dim_strides = newStrides;
}

void ArrayInfo::modDims(const dim4 &newDims)
{
    dim_size   = newDims;
    modStrides(calcStrides(newDims));
}
<commit_msg>BUG Fix: calcStride was accessing out of bounds.<commit_after>#include <ArrayInfo.hpp>
#include <numeric>
#include <algorithm>
#include <functional>

using af::dim4;
using std::partial_sum;
using std::accumulate;
using std::transform;

dim_type
calcOffset(const af::dim4 &strides, const af::dim4 &offsets)
{
    dim_type offset = 0;
    for (int i = 0; i < 4; i++) offset += offsets[i] * strides[i];
    return offset;
}

const ArrayInfo&
getInfo(af_array arr)
{
    const ArrayInfo *info = static_cast<ArrayInfo*>(reinterpret_cast<void *>(arr));
    return *info;
}

af_err
af_get_elements(dim_type *elems, const af_array arr)
{
    *elems =  getInfo(arr).elements();
    return AF_SUCCESS; //FIXME: Catch exceptions correctly
}

af_err af_get_type(af_dtype *type, const af_array arr)
{
    *type = getInfo(arr).getType();
    return AF_SUCCESS; //FIXME: Catch exceptions correctly
}

dim4 calcStrides(const dim4 &parentDim)
{
    dim_type out_dims[4] = {1, 1, 1, 1};
    const dim_type *parentPtr = parentDim.get();
    partial_sum(parentPtr, parentPtr + parentDim.ndims(), out_dims, std::multiplies<dim_type>());
    dim4 out(1, out_dims[0], out_dims[1], out_dims[2]);
    return out;
}

void ArrayInfo::modStrides(const dim4 &newStrides)
{
    dim_strides = newStrides;
}

void ArrayInfo::modDims(const dim4 &newDims)
{
    dim_size   = newDims;
    modStrides(calcStrides(newDims));
}
<|endoftext|>


<commit_before>//===--- SILCoverageMap.cpp - Defines the SILCoverageMap class ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the SILCoverageMap class, which is used to relay coverage
// mapping information from the AST to lower layers of the compiler.
//
//===----------------------------------------------------------------------===//

#include "swift/SIL/SILCoverageMap.h"
#include "swift/SIL/SILModule.h"

using namespace swift;

using llvm::coverage::CounterExpression;

SILCoverageMap *
SILCoverageMap::create(SILModule &M, StringRef Filename, StringRef Name,
                       bool External, uint64_t Hash,
                       ArrayRef<MappedRegion> MappedRegions,
                       ArrayRef<CounterExpression> Expressions) {
  void *Buf = M.allocate(sizeof(SILCoverageMap), alignof(SILCoverageMap));
  SILCoverageMap *CM = ::new (Buf) SILCoverageMap(Hash, External);

  // Store a copy of the name so that we own the lifetime.
  char *AllocatedName = (char *)M.allocate(Filename.size(), alignof(char));
  memcpy(AllocatedName, Filename.data(), Filename.size());
  CM->Filename = StringRef(AllocatedName, Filename.size());

  AllocatedName = (char *)M.allocate(Name.size(), alignof(char));
  memcpy(AllocatedName, Name.data(), Name.size());
  CM->Name = StringRef(AllocatedName, Name.size());

  // Since we have two arrays, we need to manually tail allocate each of them,
  // rather than relying on the flexible array trick.
  size_t MappedRegionsSize = sizeof(MappedRegion) * MappedRegions.size();
  CM->MappedRegions =
      (MappedRegion *)M.allocate(MappedRegionsSize, alignof(MappedRegion));
  CM->NumMappedRegions = MappedRegions.size();
  memcpy(CM->MappedRegions, MappedRegions.begin(), MappedRegionsSize);

  size_t ExpressionsSize = sizeof(CounterExpression) * Expressions.size();
  CM->Expressions = (CounterExpression *)M.allocate(ExpressionsSize,
                                                    alignof(CounterExpression));
  CM->NumExpressions = Expressions.size();
  memcpy(CM->Expressions, Expressions.begin(), ExpressionsSize);

  M.coverageMaps.push_back(CM);
  return CM;
}

SILCoverageMap::SILCoverageMap(uint64_t Hash, bool External)
    : Hash(Hash), External(External) {}

SILCoverageMap::~SILCoverageMap() {}

namespace {
struct Printer {
  const llvm::coverage::Counter &C;
  ArrayRef<llvm::coverage::CounterExpression> Exprs;
  Printer(const llvm::coverage::Counter &C,
          ArrayRef<llvm::coverage::CounterExpression> Exprs)
      : C(C), Exprs(Exprs) {}

  void print(raw_ostream &OS) const {
    // TODO: This format's nice and human readable, but does it fit well with
    // SIL's relatively simple structure?
    if (C.isZero())
      OS << "zero";
    else if (C.isExpression()) {
      assert(C.getExpressionID() < Exprs.size() && "expression out of range");
      const auto &E = Exprs[C.getExpressionID()];
      OS << '(' << Printer(E.LHS, Exprs)
         << (E.Kind == CounterExpression::Add ? " + " : " - ")
         << Printer(E.RHS, Exprs) << ')';
    } else
      OS << C.getCounterID();
  }

  friend raw_ostream &operator<<(raw_ostream &OS, const Printer &P) {
    P.print(OS);
    return OS;
  }
};
}

void SILCoverageMap::printCounter(llvm::raw_ostream &OS,
                                  llvm::coverage::Counter C) const {
  OS << Printer(C, getExpressions());
}
<commit_msg>Silence a warning.<commit_after>//===--- SILCoverageMap.cpp - Defines the SILCoverageMap class ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the SILCoverageMap class, which is used to relay coverage
// mapping information from the AST to lower layers of the compiler.
//
//===----------------------------------------------------------------------===//

#include "swift/SIL/SILCoverageMap.h"
#include "swift/SIL/SILModule.h"

using namespace swift;

using llvm::coverage::CounterExpression;

SILCoverageMap *
SILCoverageMap::create(SILModule &M, StringRef Filename, StringRef Name,
                       bool External, uint64_t Hash,
                       ArrayRef<MappedRegion> MappedRegions,
                       ArrayRef<CounterExpression> Expressions) {
  void *Buf = M.allocate(sizeof(SILCoverageMap), alignof(SILCoverageMap));
  SILCoverageMap *CM = ::new (Buf) SILCoverageMap(Hash, External);

  // Store a copy of the name so that we own the lifetime.
  char *AllocatedName = (char *)M.allocate(Filename.size(), alignof(char));
  memcpy(AllocatedName, Filename.data(), Filename.size());
  CM->Filename = StringRef(AllocatedName, Filename.size());

  AllocatedName = (char *)M.allocate(Name.size(), alignof(char));
  memcpy(AllocatedName, Name.data(), Name.size());
  CM->Name = StringRef(AllocatedName, Name.size());

  // Since we have two arrays, we need to manually tail allocate each of them,
  // rather than relying on the flexible array trick.
  size_t MappedRegionsSize = sizeof(MappedRegion) * MappedRegions.size();
  CM->MappedRegions =
      (MappedRegion *)M.allocate(MappedRegionsSize, alignof(MappedRegion));
  CM->NumMappedRegions = MappedRegions.size();
  memcpy(CM->MappedRegions, MappedRegions.begin(), MappedRegionsSize);

  size_t ExpressionsSize = sizeof(CounterExpression) * Expressions.size();
  CM->Expressions = (CounterExpression *)M.allocate(ExpressionsSize,
                                                    alignof(CounterExpression));
  CM->NumExpressions = Expressions.size();
  memcpy(CM->Expressions, Expressions.begin(), ExpressionsSize);

  M.coverageMaps.push_back(CM);
  return CM;
}

SILCoverageMap::SILCoverageMap(uint64_t Hash, bool External)
    : External(External), Hash(Hash) {}

SILCoverageMap::~SILCoverageMap() {}

namespace {
struct Printer {
  const llvm::coverage::Counter &C;
  ArrayRef<llvm::coverage::CounterExpression> Exprs;
  Printer(const llvm::coverage::Counter &C,
          ArrayRef<llvm::coverage::CounterExpression> Exprs)
      : C(C), Exprs(Exprs) {}

  void print(raw_ostream &OS) const {
    // TODO: This format's nice and human readable, but does it fit well with
    // SIL's relatively simple structure?
    if (C.isZero())
      OS << "zero";
    else if (C.isExpression()) {
      assert(C.getExpressionID() < Exprs.size() && "expression out of range");
      const auto &E = Exprs[C.getExpressionID()];
      OS << '(' << Printer(E.LHS, Exprs)
         << (E.Kind == CounterExpression::Add ? " + " : " - ")
         << Printer(E.RHS, Exprs) << ')';
    } else
      OS << C.getCounterID();
  }

  friend raw_ostream &operator<<(raw_ostream &OS, const Printer &P) {
    P.print(OS);
    return OS;
  }
};
}

void SILCoverageMap::printCounter(llvm::raw_ostream &OS,
                                  llvm::coverage::Counter C) const {
  OS << Printer(C, getExpressions());
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <iostream>

#include "bench.h"
#include "bloom.h"
#include "utiltime.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha256.h"
#include "crypto/sha512.h"

/* Number of bytes to hash per iteration */
static const uint64_t BUFFER_SIZE = 1000*1000;

static void RIPEMD160(benchmark::State& state)
{
    uint8_t hash[CRIPEMD160::OUTPUT_SIZE];
    std::vector<uint8_t> in(BUFFER_SIZE,0);
    while (state.KeepRunning())
        CRIPEMD160().Write(begin_ptr(in), in.size()).Finalize(hash);
}

static void SHA1(benchmark::State& state)
{
    uint8_t hash[CSHA1::OUTPUT_SIZE];
    std::vector<uint8_t> in(BUFFER_SIZE,0);
    while (state.KeepRunning())
        CSHA1().Write(begin_ptr(in), in.size()).Finalize(hash);
}

static void SHA256(benchmark::State& state)
{
    uint8_t hash[CSHA256::OUTPUT_SIZE];
    std::vector<uint8_t> in(BUFFER_SIZE,0);
    while (state.KeepRunning())
        CSHA256().Write(begin_ptr(in), in.size()).Finalize(hash);
}

static void SHA512(benchmark::State& state)
{
    uint8_t hash[CSHA512::OUTPUT_SIZE];
    std::vector<uint8_t> in(BUFFER_SIZE,0);
    while (state.KeepRunning())
        CSHA512().Write(begin_ptr(in), in.size()).Finalize(hash);
}

BENCHMARK(RIPEMD160);
BENCHMARK(SHA1);
BENCHMARK(SHA256);
BENCHMARK(SHA512);
<commit_msg>FastRandom benchmark<commit_after>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <iostream>

#include "bench.h"
#include "bloom.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha256.h"
#include "crypto/sha512.h"
#include "random.h"
#include "utiltime.h"

/* Number of bytes to hash per iteration */
static const uint64_t BUFFER_SIZE = 1000*1000;

static void RIPEMD160(benchmark::State& state)
{
    uint8_t hash[CRIPEMD160::OUTPUT_SIZE];
    std::vector<uint8_t> in(BUFFER_SIZE,0);
    while (state.KeepRunning())
        CRIPEMD160().Write(begin_ptr(in), in.size()).Finalize(hash);
}

static void SHA1(benchmark::State& state)
{
    uint8_t hash[CSHA1::OUTPUT_SIZE];
    std::vector<uint8_t> in(BUFFER_SIZE,0);
    while (state.KeepRunning())
        CSHA1().Write(begin_ptr(in), in.size()).Finalize(hash);
}

static void SHA256(benchmark::State& state)
{
    uint8_t hash[CSHA256::OUTPUT_SIZE];
    std::vector<uint8_t> in(BUFFER_SIZE,0);
    while (state.KeepRunning())
        CSHA256().Write(begin_ptr(in), in.size()).Finalize(hash);
}

static void SHA512(benchmark::State& state)
{
    uint8_t hash[CSHA512::OUTPUT_SIZE];
    std::vector<uint8_t> in(BUFFER_SIZE,0);
    while (state.KeepRunning())
        CSHA512().Write(begin_ptr(in), in.size()).Finalize(hash);
}

static void FastRandom_32bit(benchmark::State& state)
{
    FastRandomContext rng(true);
    uint32_t x;
    while (state.KeepRunning()) {
        for (int i = 0; i < 1000000; i++) {
            x += rng.rand32();
        }
    }
}

static void FastRandom_1bit(benchmark::State& state)
{
    FastRandomContext rng(true);
    uint32_t x;
    while (state.KeepRunning()) {
        for (int i = 0; i < 1000000; i++) {
            x += rng.randbool();
        }
    }
}

BENCHMARK(RIPEMD160);
BENCHMARK(SHA1);
BENCHMARK(SHA256);
BENCHMARK(SHA512);

BENCHMARK(FastRandom_32bit);
BENCHMARK(FastRandom_1bit);
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: pyWidget.C,v 1.17 2003/04/01 16:26:38 amoll Exp $

#include <BALL/VIEW/GUI/WIDGETS/pyWidget.h>
#include <BALL/VIEW/GUI/KERNEL/mainControl.h>
#include <BALL/VIEW/GUI/DIALOGS/pythonSettings.h>
#include <BALL/PYTHON/pyInterpreter.h>
#include <BALL/VIEW/GUI/DIALOGS/preferences.h>
#include <BALL/FORMAT/lineBasedFile.h>
#include <Python.h>

#include <qscrollbar.h>
#include <qfiledialog.h>

namespace BALL
{
	namespace VIEW
	{

PyWidget::PyWidget(QWidget* parent, const char* name)
	: QTextEdit(parent, name),
		ModularWidget(name)
{
	// register the widget with the MainControl
	ModularWidget::registerWidget(this);
}

PyWidget::PyWidget(const PyWidget& widget)
	:	QTextEdit(),
		ModularWidget(widget)
{
	ModularWidget::registerWidget(this);
}

PyWidget::~PyWidget()
	throw()
{
}

void PyWidget::initializeWidget(MainControl& main_control)
{
	main_control.insertMenuEntry(MainControl::TOOLS, "Restart Python", this, SLOT(startInterpreter()));
	main_control.insertMenuEntry(MainControl::TOOLS, "Run Python Script", this, SLOT(scriptDialog()));
	main_control.insertMenuEntry(MainControl::TOOLS, "Export History", this, SLOT(exportHistory()));
}

void PyWidget::finalizeWidget(MainControl& main_control)
{
	main_control.removeMenuEntry(MainControl::TOOLS, "Restart Python", this, SLOT(startInterpreter()));
	main_control.removeMenuEntry(MainControl::TOOLS, "Run Python Script", this, SLOT(scriptDialog()));
	main_control.removeMenuEntry(MainControl::TOOLS, "Export History", this, SLOT(exportHistory()));
}

void PyWidget::stopInterpreter()
{
	PyInterpreter::finalize();
}

void PyWidget::startInterpreter()
{
	// initialize the interpreter
	PyInterpreter::initialize();

	// print the PyBALL version and clear
	// the widget's contents in case of a restart
	setText((String("BALL ") + VersionInfo::getVersion()).c_str());

	// print the first prompt
	multi_line_mode_ = false;
	newPrompt_();
	history_position_ = history_.size() + 1;
}

void PyWidget::retrieveHistoryLine_(Position index)
{
	if (index > history_.size())
	{
		history_position_ = history_.size();
		return;
	}

	int row, col;
	getCursorPosition(&row, &col);

	if (index == history_.size())
	{
		history_position_ = history_.size();
		removeParagraph(row);
		insertParagraph(getPrompt_(), row);
		setCursorPosition(row, col);
		QScrollBar* sb = verticalScrollBar();
		if (sb != 0)
		{
			sb->setValue(sb->maxValue());
		}
		return;
	}

	String line = getPrompt_()+ history_[index];

	// replace the line's contents
	removeParagraph(row);
	insertParagraph(line.c_str(), row);
	setCursorPosition(row, line.size());
	QScrollBar* sb = verticalScrollBar();
	if (sb != 0)
	{
		sb->setValue(sb->maxValue());
	}

	// update the history position
	history_position_ = index;
}

void PyWidget::mousePressEvent(QMouseEvent* /* m */)
{
	// we ignore the mouse events!
	// they might place the cursor anywhere!
}

bool PyWidget::returnPressed()
{
	// check for an empty line (respect the prompt)
	int row, col;
	getCursorPosition(&row, &col);
	current_line_ = getCurrentLine_();
	if (col < 5)
	{
		if (multi_line_mode_)
		{
			// in multi line mode: end of input - parse it!
			QTextEdit::returnPressed();
			parseLine_();
		}
		else
		{
			// return on an empty line is handled
			// as in the interactive interpreter: do nothing and
			// print another prompt
			QTextEdit::returnPressed();
			newPrompt_();
		}
	}
	else
	{
		// parse the line
		QTextEdit::returnPressed();
		parseLine_();
	}

	return false;
}

void PyWidget::parseLine_()
{
	if (!Py_IsInitialized())
	{
		append("ERROR: no interpreter running!\n");
		return;
	}

	history_position_ = history_.size();

	String line = current_line_.getSubstring(4);
	line.trimRight();

	if (!multi_line_mode_)
	{
		if (line.isEmpty()) return;
		if ((line.hasPrefix("for ") 		||
				 line.hasPrefix("def ") 		||
				 line.hasPrefix("class ") 	||
				 line.hasPrefix("while ")	||
				 line.hasPrefix("if "))
				&& line.hasSuffix(":"))
		{
				multi_line_mode_ = true;
				multi_line_text_ = line;
				multi_line_text_.append("\n");
				multi_lines_ = 1;
				appendToHistory_(line);
				newPrompt_();
				return;
		}

		multi_lines_ = 0;
		appendToHistory_(line);
	}
	else // Multiline mode
	{
		multi_lines_ += 1;
		appendToHistory_(line);
		if (!line.isEmpty())
		{
			multi_line_text_ += line + "\n";
			newPrompt_();
			return;
		}

		line = multi_line_text_ + "\n";
	}

	bool state;
	String result = PyInterpreter::run(line, state);
	if (result != "") append(result.c_str());

	if (!multi_line_mode_)
	{
		results_.push_back(state);
	}
	else
	{
		for (Position p = 0; p <= multi_lines_ -1; p++) results_.push_back(state);
	}

	multi_line_mode_ = false;

	newPrompt_();
}

void PyWidget::appendToHistory_(const String& line)
{
	history_.push_back(line);
	history_position_ = history_.size();
}

const char* PyWidget::getPrompt_() const
{
	return (multi_line_mode_ ? "... " : ">>> ");
}

void PyWidget::newPrompt_()
{
	append(getPrompt_());
	setCursorPosition(lines() - 1, 4);
}

void PyWidget::keyPressEvent(QKeyEvent* e)
{
	int row, col;
	getCursorPosition(&row, &col);

	if (e->key() == Key_Left || e->key() == Key_Backspace)
	{
		if (col <= 4) return;
	}
	else if (e->key() == Key_Right)
	{
		setCursorPosition(row, col+1);
		return;
	}
	else if (e->key() == Key_Up)
	{
		if (history_position_ != 0) retrieveHistoryLine_(history_position_ - 1);
		return;
	}
	else if (e->key() == Key_Down)
	{
		retrieveHistoryLine_(history_position_ + 1);
		return;
	}
	else if (e->key() == Key_Home)
	{
		setCursorPosition(row, 4);
		return;
	}
	else if (e->key() == Key_Return)
	{
		if (!returnPressed()) return;
	}

	QTextEdit::keyPressEvent(e);
}

void PyWidget::dump(std::ostream& s, Size depth) const
	throw()
{
	BALL_DUMP_STREAM_PREFIX(s);

	BALL_DUMP_HEADER(s, this, this);

	BALL_DUMP_DEPTH(s, depth);
	s << "multiline_mode : " << multi_line_mode_<< std::endl;

	BALL_DUMP_DEPTH(s, depth);
	s << "multi_line_text  : " << multi_line_text_<< std::endl;

	BALL_DUMP_DEPTH(s, depth);
	s << "history : "<< std::endl;

	for (Position i = 0; i < history_.size(); i++)
	{
		BALL_DUMP_DEPTH(s, depth);
		s << history_[i]<< std::endl;
	}

	BALL_DUMP_DEPTH(s, depth);
	s << "history_position : " << history_position_ << std::endl;

	BALL_DUMP_DEPTH(s, depth);
	s << "current_line : " << current_line_ << std::endl;

	BALL_DUMP_STREAM_SUFFIX(s);
}

String PyWidget::getCurrentLine_()
{
	int row, col;
	getCursorPosition(&row, &col);
	return String(text(row).ascii());
}

void PyWidget::runFile(const String& filename)
{
	append(String("> running File " + filename + "\n").c_str());
	bool result;
	String result_string;
	LineBasedFile file;
	try
	{
		file.open(filename);
	}
	catch(Exception::GeneralException e)
	{
		append(String("> Could not find file " + filename + "\n").c_str());
		newPrompt_();
		return;
	}

	while (file.readLine())
	{
		result_string = PyInterpreter::run(file.getLine(), result);
		if (!result)
		{
			result_string += "> Error in Line " + String(file.getLineNumber()) + " in file " + filename + "\n";
			append(result_string.c_str());
			newPrompt_();
			return;
		}

		append(result_string.c_str());
	}
	append("> finished...");
	newPrompt_();
}

void PyWidget::scriptDialog()
{
	// no throw specifier because of that #$%@* moc
	QFileDialog *fd = new QFileDialog(this, "Run Python Script", true);
	fd->setMode(QFileDialog::ExistingFile);
	fd->addFilter("Python Scripts(*.py)");
	fd->setSelectedFilter(1);

	fd->setCaption("Run Python Script");
	fd->setViewMode(QFileDialog::Detail);
	fd->setGeometry(300, 150, 400, 400);

	int result_dialog = fd->exec();
	if (!result_dialog == QDialog::Accepted) return;

	String filename(fd->selectedFile().ascii());

	runFile(filename);
}

void PyWidget::fetchPreferences(INIFile& inifile)
	throw()
{
	if (!inifile.hasEntry("PYTHON", "StartupScript")) return;

	startup_script_ =	inifile.getValue("PYTHON", "StartupScript");
	python_settings_->setFilename(startup_script_);
	if (startup_script_ != "") runFile(startup_script_);
}

void PyWidget::writePreferences(INIFile& inifile)
	throw()
{
	inifile.appendSection("PYTHON");
	inifile.insertValue("PYTHON", "StartupScript", startup_script_);
}

void PyWidget::initializePreferencesTab(Preferences &preferences)
	throw()
{
	python_settings_= new PythonSettings(this);
	python_settings_->setFilename(startup_script_);
	CHECK_PTR(python_settings_);

	preferences.insertTab(python_settings_, "Python");
}

void PyWidget::finalizePreferencesTab(Preferences &preferences)
	throw()
{
	if (python_settings_ != 0)
	{
		preferences.removeTab(python_settings_);

		delete python_settings_;
		python_settings_ = 0;
	}
}

void PyWidget::applyPreferences(Preferences & /* preferences */)
	throw()
{
	if (python_settings_ == 0) return;
	startup_script_ = python_settings_->getFilename();
}

void PyWidget::cancelPreferences(Preferences&)
	throw()
{
	if (python_settings_ != 0)
	{
		python_settings_->setFilename(startup_script_);
	}
}

void PyWidget::exportHistory()
{
	QFileDialog *fd = new QFileDialog(this, "Export History", true);
	fd->setMode(QFileDialog::AnyFile);
	fd->addFilter("Python Scripts(*.py)");
	fd->setSelectedFilter(1);

	fd->setCaption("Export History");
	fd->setViewMode(QFileDialog::Detail);
	fd->setGeometry(300, 150, 400, 400);

	int result_dialog = fd->exec();
	if (!result_dialog == QDialog::Accepted) return;

	String filename(fd->selectedFile().ascii());

	File file(filename, std::ios::out);
	if (!file.isOpen())
	{
		append(String("> Could not export history to file " + filename + "\n").c_str());
		newPrompt_();
		return;
	}

	for (Position p = 0; p < history_.size(); p++)
	{
		if (results_[p]) file << history_[p] << std::endl;
	}

	file.close();
}

} } // namespace
<commit_msg>fixed: mousePressEvent is no longer needed (or supported)<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: pyWidget.C,v 1.18 2003/04/12 10:03:10 oliver Exp $

#include <BALL/VIEW/GUI/WIDGETS/pyWidget.h>
#include <BALL/VIEW/GUI/KERNEL/mainControl.h>
#include <BALL/VIEW/GUI/DIALOGS/pythonSettings.h>
#include <BALL/PYTHON/pyInterpreter.h>
#include <BALL/VIEW/GUI/DIALOGS/preferences.h>
#include <BALL/FORMAT/lineBasedFile.h>
#include <Python.h>

#include <qscrollbar.h>
#include <qfiledialog.h>

namespace BALL
{
	namespace VIEW
	{

PyWidget::PyWidget(QWidget* parent, const char* name)
	: QTextEdit(parent, name),
		ModularWidget(name)
{
	// register the widget with the MainControl
	ModularWidget::registerWidget(this);
}

PyWidget::PyWidget(const PyWidget& widget)
	:	QTextEdit(),
		ModularWidget(widget)
{
	ModularWidget::registerWidget(this);
}

PyWidget::~PyWidget()
	throw()
{
}

void PyWidget::initializeWidget(MainControl& main_control)
{
	main_control.insertMenuEntry(MainControl::TOOLS, "Restart Python", this, SLOT(startInterpreter()));
	main_control.insertMenuEntry(MainControl::TOOLS, "Run Python Script", this, SLOT(scriptDialog()));
	main_control.insertMenuEntry(MainControl::TOOLS, "Export History", this, SLOT(exportHistory()));
}

void PyWidget::finalizeWidget(MainControl& main_control)
{
	main_control.removeMenuEntry(MainControl::TOOLS, "Restart Python", this, SLOT(startInterpreter()));
	main_control.removeMenuEntry(MainControl::TOOLS, "Run Python Script", this, SLOT(scriptDialog()));
	main_control.removeMenuEntry(MainControl::TOOLS, "Export History", this, SLOT(exportHistory()));
}

void PyWidget::stopInterpreter()
{
	PyInterpreter::finalize();
}

void PyWidget::startInterpreter()
{
	// initialize the interpreter
	PyInterpreter::initialize();

	// print the PyBALL version and clear
	// the widget's contents in case of a restart
	setText((String("BALL ") + VersionInfo::getVersion()).c_str());

	// print the first prompt
	multi_line_mode_ = false;
	newPrompt_();
	history_position_ = history_.size() + 1;
}

void PyWidget::retrieveHistoryLine_(Position index)
{
	if (index > history_.size())
	{
		history_position_ = history_.size();
		return;
	}

	int row, col;
	getCursorPosition(&row, &col);

	if (index == history_.size())
	{
		history_position_ = history_.size();
		removeParagraph(row);
		insertParagraph(getPrompt_(), row);
		setCursorPosition(row, col);
		QScrollBar* sb = verticalScrollBar();
		if (sb != 0)
		{
			sb->setValue(sb->maxValue());
		}
		return;
	}

	String line = getPrompt_()+ history_[index];

	// replace the line's contents
	removeParagraph(row);
	insertParagraph(line.c_str(), row);
	setCursorPosition(row, line.size());
	QScrollBar* sb = verticalScrollBar();
	if (sb != 0)
	{
		sb->setValue(sb->maxValue());
	}

	// update the history position
	history_position_ = index;
}

bool PyWidget::returnPressed()
{
	// check for an empty line (respect the prompt)
	int row, col;
	getCursorPosition(&row, &col);
	current_line_ = getCurrentLine_();
	if (col < 5)
	{
		if (multi_line_mode_)
		{
			// in multi line mode: end of input - parse it!
			QTextEdit::returnPressed();
			parseLine_();
		}
		else
		{
			// return on an empty line is handled
			// as in the interactive interpreter: do nothing and
			// print another prompt
			QTextEdit::returnPressed();
			newPrompt_();
		}
	}
	else
	{
		// parse the line
		QTextEdit::returnPressed();
		parseLine_();
	}

	return false;
}

void PyWidget::parseLine_()
{
	if (!Py_IsInitialized())
	{
		append("ERROR: no interpreter running!\n");
		return;
	}

	history_position_ = history_.size();

	String line = current_line_.getSubstring(4);
	line.trimRight();

	if (!multi_line_mode_)
	{
		if (line.isEmpty()) return;
		if ((line.hasPrefix("for ") 		||
				 line.hasPrefix("def ") 		||
				 line.hasPrefix("class ") 	||
				 line.hasPrefix("while ")	||
				 line.hasPrefix("if "))
				&& line.hasSuffix(":"))
		{
				multi_line_mode_ = true;
				multi_line_text_ = line;
				multi_line_text_.append("\n");
				multi_lines_ = 1;
				appendToHistory_(line);
				newPrompt_();
				return;
		}

		multi_lines_ = 0;
		appendToHistory_(line);
	}
	else // Multiline mode
	{
		multi_lines_ += 1;
		appendToHistory_(line);
		if (!line.isEmpty())
		{
			multi_line_text_ += line + "\n";
			newPrompt_();
			return;
		}

		line = multi_line_text_ + "\n";
	}

	bool state;
	String result = PyInterpreter::run(line, state);
	if (result != "") append(result.c_str());

	if (!multi_line_mode_)
	{
		results_.push_back(state);
	}
	else
	{
		for (Position p = 0; p <= multi_lines_ -1; p++) results_.push_back(state);
	}

	multi_line_mode_ = false;

	newPrompt_();
}

void PyWidget::appendToHistory_(const String& line)
{
	history_.push_back(line);
	history_position_ = history_.size();
}

const char* PyWidget::getPrompt_() const
{
	return (multi_line_mode_ ? "... " : ">>> ");
}

void PyWidget::newPrompt_()
{
	append(getPrompt_());
	setCursorPosition(lines() - 1, 4);
}

void PyWidget::keyPressEvent(QKeyEvent* e)
{
	int row, col;
	getCursorPosition(&row, &col);

	if (e->key() == Key_Left || e->key() == Key_Backspace)
	{
		if (col <= 4) return;
	}
	else if (e->key() == Key_Right)
	{
		setCursorPosition(row, col+1);
		return;
	}
	else if (e->key() == Key_Up)
	{
		if (history_position_ != 0) retrieveHistoryLine_(history_position_ - 1);
		return;
	}
	else if (e->key() == Key_Down)
	{
		retrieveHistoryLine_(history_position_ + 1);
		return;
	}
	else if (e->key() == Key_Home)
	{
		setCursorPosition(row, 4);
		return;
	}
	else if (e->key() == Key_Return)
	{
		if (!returnPressed()) return;
	}

	QTextEdit::keyPressEvent(e);
}

void PyWidget::dump(std::ostream& s, Size depth) const
	throw()
{
	BALL_DUMP_STREAM_PREFIX(s);

	BALL_DUMP_HEADER(s, this, this);

	BALL_DUMP_DEPTH(s, depth);
	s << "multiline_mode : " << multi_line_mode_<< std::endl;

	BALL_DUMP_DEPTH(s, depth);
	s << "multi_line_text  : " << multi_line_text_<< std::endl;

	BALL_DUMP_DEPTH(s, depth);
	s << "history : "<< std::endl;

	for (Position i = 0; i < history_.size(); i++)
	{
		BALL_DUMP_DEPTH(s, depth);
		s << history_[i]<< std::endl;
	}

	BALL_DUMP_DEPTH(s, depth);
	s << "history_position : " << history_position_ << std::endl;

	BALL_DUMP_DEPTH(s, depth);
	s << "current_line : " << current_line_ << std::endl;

	BALL_DUMP_STREAM_SUFFIX(s);
}

String PyWidget::getCurrentLine_()
{
	int row, col;
	getCursorPosition(&row, &col);
	return String(text(row).ascii());
}

void PyWidget::runFile(const String& filename)
{
	append(String("> running File " + filename + "\n").c_str());
	bool result;
	String result_string;
	LineBasedFile file;
	try
	{
		file.open(filename);
	}
	catch(Exception::GeneralException e)
	{
		append(String("> Could not find file " + filename + "\n").c_str());
		newPrompt_();
		return;
	}

	while (file.readLine())
	{
		result_string = PyInterpreter::run(file.getLine(), result);
		if (!result)
		{
			result_string += "> Error in Line " + String(file.getLineNumber()) + " in file " + filename + "\n";
			append(result_string.c_str());
			newPrompt_();
			return;
		}

		append(result_string.c_str());
	}
	append("> finished...");
	newPrompt_();
}

void PyWidget::scriptDialog()
{
	// no throw specifier because of that #$%@* moc
	QFileDialog *fd = new QFileDialog(this, "Run Python Script", true);
	fd->setMode(QFileDialog::ExistingFile);
	fd->addFilter("Python Scripts(*.py)");
	fd->setSelectedFilter(1);

	fd->setCaption("Run Python Script");
	fd->setViewMode(QFileDialog::Detail);
	fd->setGeometry(300, 150, 400, 400);

	int result_dialog = fd->exec();
	if (!result_dialog == QDialog::Accepted) return;

	String filename(fd->selectedFile().ascii());

	runFile(filename);
}

void PyWidget::fetchPreferences(INIFile& inifile)
	throw()
{
	if (!inifile.hasEntry("PYTHON", "StartupScript")) return;

	startup_script_ =	inifile.getValue("PYTHON", "StartupScript");
	python_settings_->setFilename(startup_script_);
	if (startup_script_ != "") runFile(startup_script_);
}

void PyWidget::writePreferences(INIFile& inifile)
	throw()
{
	inifile.appendSection("PYTHON");
	inifile.insertValue("PYTHON", "StartupScript", startup_script_);
}

void PyWidget::initializePreferencesTab(Preferences &preferences)
	throw()
{
	python_settings_= new PythonSettings(this);
	python_settings_->setFilename(startup_script_);
	CHECK_PTR(python_settings_);

	preferences.insertTab(python_settings_, "Python");
}

void PyWidget::finalizePreferencesTab(Preferences &preferences)
	throw()
{
	if (python_settings_ != 0)
	{
		preferences.removeTab(python_settings_);

		delete python_settings_;
		python_settings_ = 0;
	}
}

void PyWidget::applyPreferences(Preferences & /* preferences */)
	throw()
{
	if (python_settings_ == 0) return;
	startup_script_ = python_settings_->getFilename();
}

void PyWidget::cancelPreferences(Preferences&)
	throw()
{
	if (python_settings_ != 0)
	{
		python_settings_->setFilename(startup_script_);
	}
}

void PyWidget::exportHistory()
{
	QFileDialog *fd = new QFileDialog(this, "Export History", true);
	fd->setMode(QFileDialog::AnyFile);
	fd->addFilter("Python Scripts(*.py)");
	fd->setSelectedFilter(1);

	fd->setCaption("Export History");
	fd->setViewMode(QFileDialog::Detail);
	fd->setGeometry(300, 150, 400, 400);

	int result_dialog = fd->exec();
	if (!result_dialog == QDialog::Accepted) return;

	String filename(fd->selectedFile().ascii());

	File file(filename, std::ios::out);
	if (!file.isOpen())
	{
		append(String("> Could not export history to file " + filename + "\n").c_str());
		newPrompt_();
		return;
	}

	for (Position p = 0; p < history_.size(); p++)
	{
		if (results_[p]) file << history_[p] << std::endl;
	}

	file.close();
}

} } // namespace
<|endoftext|>


<commit_before>//===-- Annotation.cpp - Implement the Annotation Classes -----------------===//
//
//                     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 AnnotationManager class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Annotation.h"
#include "llvm/Support/ManagedStatic.h"
#include <map>
#include <cstring>
using namespace llvm;

Annotation::~Annotation() {}  // Designed to be subclassed

Annotable::~Annotable() {   // Virtual because it's designed to be subclassed...
  Annotation *A = AnnotationList;
  while (A) {
    Annotation *Next = A->getNext();
    delete A;
    A = Next;
  }
}

namespace {
  class StrCmp {
  public:
    bool operator()(const char *a, const char *b) const {
      return strcmp(a, b) < 0;
    }
  };
}

typedef std::map<const char*, unsigned, StrCmp> IDMapType;
static unsigned IDCounter = 0;  // Unique ID counter

// Static member to ensure initialiation on demand.
static ManagedStatic<IDMapType> IDMap;

// On demand annotation creation support...
typedef Annotation *(*AnnFactory)(AnnotationID, const Annotable *, void *);
typedef std::map<unsigned, std::pair<AnnFactory,void*> > FactMapType;

static FactMapType *TheFactMap = 0;
static FactMapType &getFactMap() {
  if (TheFactMap == 0)
    TheFactMap = new FactMapType();
  return *TheFactMap;
}

static void eraseFromFactMap(unsigned ID) {
  assert(TheFactMap && "No entries found!");
  TheFactMap->erase(ID);
  if (TheFactMap->empty()) {   // Delete when empty
    delete TheFactMap;
    TheFactMap = 0;
  }
}

AnnotationID AnnotationManager::getID(const char *Name) {  // Name -> ID
  IDMapType::iterator I = IDMap->find(Name);
  if (I == IDMap->end()) {
    (*IDMap)[Name] = IDCounter++;   // Add a new element
    return AnnotationID(IDCounter-1);
  }
  return AnnotationID(I->second);
}

// getID - Name -> ID + registration of a factory function for demand driven
// annotation support.
AnnotationID AnnotationManager::getID(const char *Name, Factory Fact,
                                      void *Data) {
  AnnotationID Result(getID(Name));
  registerAnnotationFactory(Result, Fact, Data);
  return Result;
}

// getName - This function is especially slow, but that's okay because it should
// only be used for debugging.
//
const char *AnnotationManager::getName(AnnotationID ID) {  // ID -> Name
  IDMapType &TheMap = *IDMap;
  for (IDMapType::iterator I = TheMap.begin(); ; ++I) {
    assert(I != TheMap.end() && "Annotation ID is unknown!");
    if (I->second == ID.ID) return I->first;
  }
}

// registerAnnotationFactory - This method is used to register a callback
// function used to create an annotation on demand if it is needed by the
// Annotable::findOrCreateAnnotation method.
//
void AnnotationManager::registerAnnotationFactory(AnnotationID ID, AnnFactory F,
                                                  void *ExtraData) {
  if (F)
    getFactMap()[ID.ID] = std::make_pair(F, ExtraData);
  else
    eraseFromFactMap(ID.ID);
}

// createAnnotation - Create an annotation of the specified ID for the
// specified object, using a register annotation creation function.
//
Annotation *AnnotationManager::createAnnotation(AnnotationID ID,
                                                const Annotable *Obj) {
  FactMapType::iterator I = getFactMap().find(ID.ID);
  if (I == getFactMap().end()) return 0;
  return I->second.first(ID, Obj, I->second.second);
}
<commit_msg>Guard the global annotation tables.<commit_after>//===-- Annotation.cpp - Implement the Annotation Classes -----------------===//
//
//                     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 AnnotationManager class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Annotation.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/System/RWMutex.h"
#include <map>
#include <cstring>
using namespace llvm;

Annotation::~Annotation() {}  // Designed to be subclassed

Annotable::~Annotable() {   // Virtual because it's designed to be subclassed...
  Annotation *A = AnnotationList;
  while (A) {
    Annotation *Next = A->getNext();
    delete A;
    A = Next;
  }
}

namespace {
  class StrCmp {
  public:
    bool operator()(const char *a, const char *b) const {
      return strcmp(a, b) < 0;
    }
  };
}

typedef std::map<const char*, unsigned, StrCmp> IDMapType;
static unsigned IDCounter = 0;  // Unique ID counter

// Static member to ensure initialiation on demand.
static ManagedStatic<IDMapType> IDMap;
static ManagedStatic<sys::SmartRWMutex<true> > AnnotationsLock;

// On demand annotation creation support...
typedef Annotation *(*AnnFactory)(AnnotationID, const Annotable *, void *);
typedef std::map<unsigned, std::pair<AnnFactory,void*> > FactMapType;

static ManagedStatic<FactMapType> TheFactMap;
static FactMapType &getFactMap() {
  return *TheFactMap;
}

static void eraseFromFactMap(unsigned ID) {
  sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
  TheFactMap->erase(ID);
}

AnnotationID AnnotationManager::getID(const char *Name) {  // Name -> ID
  AnnotationsLock->reader_acquire();
  IDMapType::iterator I = IDMap->find(Name);
  IDMapType::iterator E = IDMap->end();
  AnnotationsLock->reader_release();

  if (I == E) {
    sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
    I = IDMap->find(Name);
    if (I == IDMap->end())
      (*IDMap)[Name] = IDCounter++;   // Add a new element
    return AnnotationID(IDCounter-1);
  }
  return AnnotationID(I->second);
}

// getID - Name -> ID + registration of a factory function for demand driven
// annotation support.
AnnotationID AnnotationManager::getID(const char *Name, Factory Fact,
                                      void *Data) {
  AnnotationID Result(getID(Name));
  registerAnnotationFactory(Result, Fact, Data);
  return Result;
}

// getName - This function is especially slow, but that's okay because it should
// only be used for debugging.
//
const char *AnnotationManager::getName(AnnotationID ID) {  // ID -> Name
  sys::SmartScopedReader<true> Reader(&*AnnotationsLock);
  IDMapType &TheMap = *IDMap;
  for (IDMapType::iterator I = TheMap.begin(); ; ++I) {
    assert(I != TheMap.end() && "Annotation ID is unknown!");
    if (I->second == ID.ID) return I->first;
  }
}

// registerAnnotationFactory - This method is used to register a callback
// function used to create an annotation on demand if it is needed by the
// Annotable::findOrCreateAnnotation method.
//
void AnnotationManager::registerAnnotationFactory(AnnotationID ID, AnnFactory F,
                                                  void *ExtraData) {
  if (F) {
    sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
    getFactMap()[ID.ID] = std::make_pair(F, ExtraData);
  } else {
    eraseFromFactMap(ID.ID);
  }
}

// createAnnotation - Create an annotation of the specified ID for the
// specified object, using a register annotation creation function.
//
Annotation *AnnotationManager::createAnnotation(AnnotationID ID,
                                                const Annotable *Obj) {
  AnnotationsLock->reader_acquire();
  FactMapType::iterator I = getFactMap().find(ID.ID);
  if (I == getFactMap().end()) {
    AnnotationsLock->reader_release();
    return 0;
  }

  AnnotationsLock->reader_release();
  return I->second.first(ID, Obj, I->second.second);
}
<|endoftext|>


<commit_before>//===-- SymbolTable.cpp - Implement the SymbolTable class -------------------=//
//
// This file implements the SymbolTable class for the VMCore library.
//
//===----------------------------------------------------------------------===//

#include "llvm/SymbolTable.h"
#include "llvm/InstrTypes.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "Support/StringExtras.h"
#include <iostream>

using std::string;
using std::pair;
using std::make_pair;
using std::map;
using std::cerr;

#define DEBUG_SYMBOL_TABLE 0
#define DEBUG_ABSTYPE 0

SymbolTable::~SymbolTable() {
  // Drop all abstract type references in the type plane...
  iterator TyPlane = find(Type::TypeTy);
  if (TyPlane != end()) {
    VarMap &TyP = TyPlane->second;
    for (VarMap::iterator I = TyP.begin(), E = TyP.end(); I != E; ++I) {
      const Type *Ty = cast<const Type>(I->second);
      if (Ty->isAbstract())   // If abstract, drop the reference...
	cast<DerivedType>(Ty)->removeAbstractTypeUser(this);
    }
  }

 // TODO: FIXME: BIG ONE: This doesn't unreference abstract types for the planes
 // that could still have entries!

#ifndef NDEBUG   // Only do this in -g mode...
  bool LeftoverValues = true;
  for (iterator i = begin(); i != end(); ++i) {
    for (type_iterator I = i->second.begin(); I != i->second.end(); ++I)
      if (!isa<Constant>(I->second) && !isa<Type>(I->second)) {
	cerr << "Value still in symbol table! Type = '"
             << i->first->getDescription() << "' Name = '"
             << I->first << "'\n";
	LeftoverValues = false;
      }
  }

  assert(LeftoverValues && "Values remain in symbol table!");
#endif
}

// getUniqueName - Given a base name, return a string that is either equal to
// it (or derived from it) that does not already occur in the symbol table for
// the specified type.
//
string SymbolTable::getUniqueName(const Type *Ty, const string &BaseName) {
  iterator I = find(Ty);
  if (I == end()) return BaseName;

  string TryName = BaseName;
  unsigned Counter = 0;
  type_iterator End = I->second.end();

  while (I->second.find(TryName) != End)     // Loop until we find unoccupied
    TryName = BaseName + utostr(++Counter);  // Name in the symbol table
  return TryName;
}

// lookup - Returns null on failure...
Value *SymbolTable::localLookup(const Type *Ty, const string &Name) {
  iterator I = find(Ty);
  if (I != end()) {                      // We have symbols in that plane...
    type_iterator J = I->second.find(Name);
    if (J != I->second.end())            // and the name is in our hash table...
      return J->second;
  }

  return 0;
}

// lookup - Returns null on failure...
Value *SymbolTable::lookup(const Type *Ty, const string &Name) {
  Value *LV = localLookup(Ty, Name);
  if (LV) return LV;
  return ParentSymTab ? ParentSymTab->lookup(Ty, Name) : 0;
}

void SymbolTable::remove(Value *N) {
  assert(N->hasName() && "Value doesn't have name!");
  if (InternallyInconsistent) return;

  iterator I = find(N->getType());
  assert(I != end() &&
         "Trying to remove a type that doesn't have a plane yet!");
  removeEntry(I, I->second.find(N->getName()));
}

// removeEntry - Remove a value from the symbol table...
//
Value *SymbolTable::removeEntry(iterator Plane, type_iterator Entry) {
  if (InternallyInconsistent) return 0;
  assert(Plane != super::end() &&
         Entry != Plane->second.end() && "Invalid entry to remove!");

  Value *Result = Entry->second;
  const Type *Ty = Result->getType();
#if DEBUG_SYMBOL_TABLE
  dump();
  std::cerr << " Removing Value: " << Result->getName() << "\n";
#endif

  // Remove the value from the plane...
  Plane->second.erase(Entry);

  // If the plane is empty, remove it now!
  if (Plane->second.empty()) {
    // If the plane represented an abstract type that we were interested in,
    // unlink ourselves from this plane.
    //
    if (Plane->first->isAbstract()) {
#if DEBUG_ABSTYPE
      cerr << "Plane Empty: Removing type: " << Plane->first->getDescription()
           << "\n";
#endif
      cast<DerivedType>(Plane->first)->removeAbstractTypeUser(this);
    }

    erase(Plane);
  }

  // If we are removing an abstract type, remove the symbol table from it's use
  // list...
  if (Ty == Type::TypeTy) {
    const Type *T = cast<const Type>(Result);
    if (T->isAbstract()) {
#if DEBUG_ABSTYPE
      cerr << "Removing abs type from symtab" << T->getDescription() << "\n";
#endif
      cast<DerivedType>(T)->removeAbstractTypeUser(this);
    }
  }

  return Result;
}

// insertEntry - Insert a value into the symbol table with the specified
// name...
//
void SymbolTable::insertEntry(const string &Name, const Type *VTy, Value *V) {

  // Check to see if there is a naming conflict.  If so, rename this value!
  if (localLookup(VTy, Name)) {
    string UniqueName = getUniqueName(VTy, Name);
    assert(InternallyInconsistent == false && "Infinite loop inserting entry!");
    InternallyInconsistent = true;
    V->setName(UniqueName, this);
    InternallyInconsistent = false;
    return;
  }

#if DEBUG_SYMBOL_TABLE
  dump();
  cerr << " Inserting definition: " << Name << ": "
       << VTy->getDescription() << "\n";
#endif

  iterator I = find(VTy);
  if (I == end()) {      // Not in collection yet... insert dummy entry
    // Insert a new empty element.  I points to the new elements.
    I = super::insert(make_pair(VTy, VarMap())).first;
    assert(I != end() && "How did insert fail?");

    // Check to see if the type is abstract.  If so, it might be refined in the
    // future, which would cause the plane of the old type to get merged into
    // a new type plane.
    //
    if (VTy->isAbstract()) {
      cast<DerivedType>(VTy)->addAbstractTypeUser(this);
#if DEBUG_ABSTYPE
      cerr << "Added abstract type value: " << VTy->getDescription() << "\n";
#endif
    }
  }

  I->second.insert(make_pair(Name, V));

  // If we are adding an abstract type, add the symbol table to it's use list.
  if (VTy == Type::TypeTy) {
    const Type *T = cast<const Type>(V);
    if (T->isAbstract()) {
      cast<DerivedType>(T)->addAbstractTypeUser(this);
#if DEBUG_ABSTYPE
      cerr << "Added abstract type to ST: " << T->getDescription() << "\n";
#endif
    }
  }
}

// This function is called when one of the types in the type plane are refined
void SymbolTable::refineAbstractType(const DerivedType *OldType,
				     const Type *NewType) {
  if (OldType == NewType && OldType->isAbstract())
    return;  // Noop, don't waste time dinking around

  // Search to see if we have any values of the type oldtype.  If so, we need to
  // move them into the newtype plane...
  iterator TPI = find(OldType);
  if (OldType != NewType && TPI != end()) {
    // Get a handle to the new type plane...
    iterator NewTypeIt = find(NewType);
    if (NewTypeIt == super::end()) {      // If no plane exists, add one
      NewTypeIt = super::insert(make_pair(NewType, VarMap())).first;

      if (NewType->isAbstract()) {
        cast<DerivedType>(NewType)->addAbstractTypeUser(this);
#if DEBUG_ABSTYPE
        cerr << "[Added] refined to abstype: "<<NewType->getDescription()<<"\n";
#endif
      }
    }

    VarMap &NewPlane = NewTypeIt->second;
    VarMap &OldPlane = TPI->second;
    while (!OldPlane.empty()) {
      pair<const string, Value*> V = *OldPlane.begin();

      // Check to see if there is already a value in the symbol table that this
      // would collide with.
      type_iterator TI = NewPlane.find(V.first);
      if (TI != NewPlane.end() && TI->second == V.second) {
        // No action

      } else if (TI != NewPlane.end()) {
        // The only thing we are allowing for now is two method prototypes being
        // folded into one.
        //
        Function *ExistM = dyn_cast<Function>(TI->second);
        Function *NewM = dyn_cast<Function>(V.second);

        if (ExistM && NewM && ExistM->isExternal() && NewM->isExternal()) {
          // Ok we have two external methods.  Make all uses of the new one
          // use the old one...
          //
          NewM->replaceAllUsesWith(ExistM);

          // Now we just convert it to an unnamed method... which won't get
          // added to our symbol table.  The problem is that if we call
          // setName on the method that it will try to remove itself from
          // the symbol table and die... because it's not in the symtab
          // right now.  To fix this, we have an internally consistent flag
          // that turns remove into a noop.  Thus the name will get null'd
          // out, but the symbol table won't get upset.
          //
          assert(InternallyInconsistent == false &&
                 "Symbol table already inconsistent!");
          InternallyInconsistent = true;

          // Remove newM from the symtab
          NewM->setName("");
          InternallyInconsistent = false;

          // Now we can remove this method from the module entirely...
          NewM->getParent()->getFunctionList().remove(NewM);
          delete NewM;

        } else {
          assert(0 && "Two ploanes folded together with overlapping "
                 "value names!");
        }
      } else {
        insertEntry(V.first, NewType, V.second);

      }
      // Remove the item from the old type plane
      OldPlane.erase(OldPlane.begin());
    }

    // Ok, now we are not referencing the type anymore... take me off your user
    // list please!
#if DEBUG_ABSTYPE
    cerr << "Removing type " << OldType->getDescription() << "\n";
#endif
    OldType->removeAbstractTypeUser(this);

    // Remove the plane that is no longer used
    erase(TPI);
  } else if (TPI != end()) {
    assert(OldType == NewType);
#if DEBUG_ABSTYPE
    cerr << "Removing SELF type " << OldType->getDescription() << "\n";
#endif
    OldType->removeAbstractTypeUser(this);
  }

  TPI = find(Type::TypeTy);
  if (TPI != end()) {
    // Loop over all of the types in the symbol table, replacing any references
    // to OldType with references to NewType.  Note that there may be multiple
    // occurances, and although we only need to remove one at a time, it's
    // faster to remove them all in one pass.
    //
    VarMap &TyPlane = TPI->second;
    for (VarMap::iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I)
      if (I->second == (Value*)OldType) {  // FIXME when Types aren't const.
#if DEBUG_ABSTYPE
        cerr << "Removing type " << OldType->getDescription() << "\n";
#endif
        OldType->removeAbstractTypeUser(this);

        I->second = (Value*)NewType;  // TODO FIXME when types aren't const
        if (NewType->isAbstract()) {
#if DEBUG_ABSTYPE
          cerr << "Added type " << NewType->getDescription() << "\n";
#endif
          cast<const DerivedType>(NewType)->addAbstractTypeUser(this);
        }
      }
  }
}

#ifndef NDEBUG
#include <algorithm>

static void DumpVal(const pair<const string, Value *> &V) {
  std::cout << "  '" << V.first << "' = ";
  V.second->dump();
  std::cout << "\n";
}

static void DumpPlane(const pair<const Type *, map<const string, Value *> >&P) {
  std::cout << "  Plane: ";
  P.first->dump();
  std::cout << "\n";
  for_each(P.second.begin(), P.second.end(), DumpVal);
}

void SymbolTable::dump() const {
  std::cout << "Symbol table dump:\n";
  for_each(begin(), end(), DumpPlane);

  if (ParentSymTab) {
    std::cout << "Parent ";
    ParentSymTab->dump();
  }
}

#endif
<commit_msg>We actually need this code for the release build to prevent link errors, un#ifdef it.<commit_after>//===-- SymbolTable.cpp - Implement the SymbolTable class -------------------=//
//
// This file implements the SymbolTable class for the VMCore library.
//
//===----------------------------------------------------------------------===//

#include "llvm/SymbolTable.h"
#include "llvm/InstrTypes.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "Support/StringExtras.h"
#include <iostream>
#include <algorithm>

using std::string;
using std::pair;
using std::make_pair;
using std::map;
using std::cerr;

#define DEBUG_SYMBOL_TABLE 0
#define DEBUG_ABSTYPE 0

SymbolTable::~SymbolTable() {
  // Drop all abstract type references in the type plane...
  iterator TyPlane = find(Type::TypeTy);
  if (TyPlane != end()) {
    VarMap &TyP = TyPlane->second;
    for (VarMap::iterator I = TyP.begin(), E = TyP.end(); I != E; ++I) {
      const Type *Ty = cast<const Type>(I->second);
      if (Ty->isAbstract())   // If abstract, drop the reference...
	cast<DerivedType>(Ty)->removeAbstractTypeUser(this);
    }
  }

 // TODO: FIXME: BIG ONE: This doesn't unreference abstract types for the planes
 // that could still have entries!

#ifndef NDEBUG   // Only do this in -g mode...
  bool LeftoverValues = true;
  for (iterator i = begin(); i != end(); ++i) {
    for (type_iterator I = i->second.begin(); I != i->second.end(); ++I)
      if (!isa<Constant>(I->second) && !isa<Type>(I->second)) {
	cerr << "Value still in symbol table! Type = '"
             << i->first->getDescription() << "' Name = '"
             << I->first << "'\n";
	LeftoverValues = false;
      }
  }

  assert(LeftoverValues && "Values remain in symbol table!");
#endif
}

// getUniqueName - Given a base name, return a string that is either equal to
// it (or derived from it) that does not already occur in the symbol table for
// the specified type.
//
string SymbolTable::getUniqueName(const Type *Ty, const string &BaseName) {
  iterator I = find(Ty);
  if (I == end()) return BaseName;

  string TryName = BaseName;
  unsigned Counter = 0;
  type_iterator End = I->second.end();

  while (I->second.find(TryName) != End)     // Loop until we find unoccupied
    TryName = BaseName + utostr(++Counter);  // Name in the symbol table
  return TryName;
}

// lookup - Returns null on failure...
Value *SymbolTable::localLookup(const Type *Ty, const string &Name) {
  iterator I = find(Ty);
  if (I != end()) {                      // We have symbols in that plane...
    type_iterator J = I->second.find(Name);
    if (J != I->second.end())            // and the name is in our hash table...
      return J->second;
  }

  return 0;
}

// lookup - Returns null on failure...
Value *SymbolTable::lookup(const Type *Ty, const string &Name) {
  Value *LV = localLookup(Ty, Name);
  if (LV) return LV;
  return ParentSymTab ? ParentSymTab->lookup(Ty, Name) : 0;
}

void SymbolTable::remove(Value *N) {
  assert(N->hasName() && "Value doesn't have name!");
  if (InternallyInconsistent) return;

  iterator I = find(N->getType());
  assert(I != end() &&
         "Trying to remove a type that doesn't have a plane yet!");
  removeEntry(I, I->second.find(N->getName()));
}

// removeEntry - Remove a value from the symbol table...
//
Value *SymbolTable::removeEntry(iterator Plane, type_iterator Entry) {
  if (InternallyInconsistent) return 0;
  assert(Plane != super::end() &&
         Entry != Plane->second.end() && "Invalid entry to remove!");

  Value *Result = Entry->second;
  const Type *Ty = Result->getType();
#if DEBUG_SYMBOL_TABLE
  dump();
  std::cerr << " Removing Value: " << Result->getName() << "\n";
#endif

  // Remove the value from the plane...
  Plane->second.erase(Entry);

  // If the plane is empty, remove it now!
  if (Plane->second.empty()) {
    // If the plane represented an abstract type that we were interested in,
    // unlink ourselves from this plane.
    //
    if (Plane->first->isAbstract()) {
#if DEBUG_ABSTYPE
      cerr << "Plane Empty: Removing type: " << Plane->first->getDescription()
           << "\n";
#endif
      cast<DerivedType>(Plane->first)->removeAbstractTypeUser(this);
    }

    erase(Plane);
  }

  // If we are removing an abstract type, remove the symbol table from it's use
  // list...
  if (Ty == Type::TypeTy) {
    const Type *T = cast<const Type>(Result);
    if (T->isAbstract()) {
#if DEBUG_ABSTYPE
      cerr << "Removing abs type from symtab" << T->getDescription() << "\n";
#endif
      cast<DerivedType>(T)->removeAbstractTypeUser(this);
    }
  }

  return Result;
}

// insertEntry - Insert a value into the symbol table with the specified
// name...
//
void SymbolTable::insertEntry(const string &Name, const Type *VTy, Value *V) {

  // Check to see if there is a naming conflict.  If so, rename this value!
  if (localLookup(VTy, Name)) {
    string UniqueName = getUniqueName(VTy, Name);
    assert(InternallyInconsistent == false && "Infinite loop inserting entry!");
    InternallyInconsistent = true;
    V->setName(UniqueName, this);
    InternallyInconsistent = false;
    return;
  }

#if DEBUG_SYMBOL_TABLE
  dump();
  cerr << " Inserting definition: " << Name << ": "
       << VTy->getDescription() << "\n";
#endif

  iterator I = find(VTy);
  if (I == end()) {      // Not in collection yet... insert dummy entry
    // Insert a new empty element.  I points to the new elements.
    I = super::insert(make_pair(VTy, VarMap())).first;
    assert(I != end() && "How did insert fail?");

    // Check to see if the type is abstract.  If so, it might be refined in the
    // future, which would cause the plane of the old type to get merged into
    // a new type plane.
    //
    if (VTy->isAbstract()) {
      cast<DerivedType>(VTy)->addAbstractTypeUser(this);
#if DEBUG_ABSTYPE
      cerr << "Added abstract type value: " << VTy->getDescription() << "\n";
#endif
    }
  }

  I->second.insert(make_pair(Name, V));

  // If we are adding an abstract type, add the symbol table to it's use list.
  if (VTy == Type::TypeTy) {
    const Type *T = cast<const Type>(V);
    if (T->isAbstract()) {
      cast<DerivedType>(T)->addAbstractTypeUser(this);
#if DEBUG_ABSTYPE
      cerr << "Added abstract type to ST: " << T->getDescription() << "\n";
#endif
    }
  }
}

// This function is called when one of the types in the type plane are refined
void SymbolTable::refineAbstractType(const DerivedType *OldType,
				     const Type *NewType) {
  if (OldType == NewType && OldType->isAbstract())
    return;  // Noop, don't waste time dinking around

  // Search to see if we have any values of the type oldtype.  If so, we need to
  // move them into the newtype plane...
  iterator TPI = find(OldType);
  if (OldType != NewType && TPI != end()) {
    // Get a handle to the new type plane...
    iterator NewTypeIt = find(NewType);
    if (NewTypeIt == super::end()) {      // If no plane exists, add one
      NewTypeIt = super::insert(make_pair(NewType, VarMap())).first;

      if (NewType->isAbstract()) {
        cast<DerivedType>(NewType)->addAbstractTypeUser(this);
#if DEBUG_ABSTYPE
        cerr << "[Added] refined to abstype: "<<NewType->getDescription()<<"\n";
#endif
      }
    }

    VarMap &NewPlane = NewTypeIt->second;
    VarMap &OldPlane = TPI->second;
    while (!OldPlane.empty()) {
      pair<const string, Value*> V = *OldPlane.begin();

      // Check to see if there is already a value in the symbol table that this
      // would collide with.
      type_iterator TI = NewPlane.find(V.first);
      if (TI != NewPlane.end() && TI->second == V.second) {
        // No action

      } else if (TI != NewPlane.end()) {
        // The only thing we are allowing for now is two method prototypes being
        // folded into one.
        //
        Function *ExistM = dyn_cast<Function>(TI->second);
        Function *NewM = dyn_cast<Function>(V.second);

        if (ExistM && NewM && ExistM->isExternal() && NewM->isExternal()) {
          // Ok we have two external methods.  Make all uses of the new one
          // use the old one...
          //
          NewM->replaceAllUsesWith(ExistM);

          // Now we just convert it to an unnamed method... which won't get
          // added to our symbol table.  The problem is that if we call
          // setName on the method that it will try to remove itself from
          // the symbol table and die... because it's not in the symtab
          // right now.  To fix this, we have an internally consistent flag
          // that turns remove into a noop.  Thus the name will get null'd
          // out, but the symbol table won't get upset.
          //
          assert(InternallyInconsistent == false &&
                 "Symbol table already inconsistent!");
          InternallyInconsistent = true;

          // Remove newM from the symtab
          NewM->setName("");
          InternallyInconsistent = false;

          // Now we can remove this method from the module entirely...
          NewM->getParent()->getFunctionList().remove(NewM);
          delete NewM;

        } else {
          assert(0 && "Two ploanes folded together with overlapping "
                 "value names!");
        }
      } else {
        insertEntry(V.first, NewType, V.second);

      }
      // Remove the item from the old type plane
      OldPlane.erase(OldPlane.begin());
    }

    // Ok, now we are not referencing the type anymore... take me off your user
    // list please!
#if DEBUG_ABSTYPE
    cerr << "Removing type " << OldType->getDescription() << "\n";
#endif
    OldType->removeAbstractTypeUser(this);

    // Remove the plane that is no longer used
    erase(TPI);
  } else if (TPI != end()) {
    assert(OldType == NewType);
#if DEBUG_ABSTYPE
    cerr << "Removing SELF type " << OldType->getDescription() << "\n";
#endif
    OldType->removeAbstractTypeUser(this);
  }

  TPI = find(Type::TypeTy);
  if (TPI != end()) {
    // Loop over all of the types in the symbol table, replacing any references
    // to OldType with references to NewType.  Note that there may be multiple
    // occurances, and although we only need to remove one at a time, it's
    // faster to remove them all in one pass.
    //
    VarMap &TyPlane = TPI->second;
    for (VarMap::iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I)
      if (I->second == (Value*)OldType) {  // FIXME when Types aren't const.
#if DEBUG_ABSTYPE
        cerr << "Removing type " << OldType->getDescription() << "\n";
#endif
        OldType->removeAbstractTypeUser(this);

        I->second = (Value*)NewType;  // TODO FIXME when types aren't const
        if (NewType->isAbstract()) {
#if DEBUG_ABSTYPE
          cerr << "Added type " << NewType->getDescription() << "\n";
#endif
          cast<const DerivedType>(NewType)->addAbstractTypeUser(this);
        }
      }
  }
}

static void DumpVal(const pair<const string, Value *> &V) {
  std::cout << "  '" << V.first << "' = ";
  V.second->dump();
  std::cout << "\n";
}

static void DumpPlane(const pair<const Type *, map<const string, Value *> >&P) {
  std::cout << "  Plane: ";
  P.first->dump();
  std::cout << "\n";
  for_each(P.second.begin(), P.second.end(), DumpVal);
}

void SymbolTable::dump() const {
  std::cout << "Symbol table dump:\n";
  for_each(begin(), end(), DumpPlane);

  if (ParentSymTab) {
    std::cout << "Parent ";
    ParentSymTab->dump();
  }
}
<|endoftext|>