<commit_before>//===-- Writer.cpp - Library for writing LLVM bytecode files --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This library implements the functionality defined in llvm/Bytecode/Writer.h
//
// Note that this file uses an unusual technique of outputting all the bytecode
// to a deque of unsigned char, then copies the deque to an ostream.  The
// reason for this is that we must do "seeking" in the stream to do back-
// patching, and some very important ostreams that we want to support (like
// pipes) do not support seeking.  :( :( :(
//
// The choice of the deque data structure is influenced by the extremely fast
// "append" speed, plus the free "seek"/replace in the middle of the stream. I
// didn't use a vector because the stream could end up very large and copying
// the whole thing to reallocate would be kinda silly.
//
//===----------------------------------------------------------------------===//

#include "WriterInternals.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include "Support/STLExtras.h"
#include "Support/Statistic.h"
#include <cstring>
#include <algorithm>
using namespace llvm;

static RegisterPass<WriteBytecodePass> X("emitbytecode", "Bytecode Writer");

static Statistic<>
BytesWritten("bytecodewriter", "Number of bytecode bytes written");

BytecodeWriter::BytecodeWriter(std::deque<unsigned char> &o, const Module *M)
  : Out(o), Table(M, true) {

  // Emit the signature...
  static const unsigned char *Sig =  (const unsigned char*)"llvm";
  output_data(Sig, Sig+4, Out);

  // Emit the top level CLASS block.
  BytecodeBlock ModuleBlock(BytecodeFormat::Module, Out);

  bool isBigEndian      = M->getEndianness() == Module::BigEndian;
  bool hasLongPointers  = M->getPointerSize() == Module::Pointer64;
  bool hasNoEndianness  = M->getEndianness() == Module::AnyEndianness;
  bool hasNoPointerSize = M->getPointerSize() == Module::AnyPointerSize;

  // Output the version identifier... we are currently on bytecode version #2,
  // which corresponds to LLVM v1.3.
  unsigned Version = (2 << 4) | isBigEndian | (hasLongPointers << 1) |
                     (hasNoEndianness << 2) | (hasNoPointerSize << 3);
  output_vbr(Version, Out);
  align32(Out);

  {
    BytecodeBlock CPool(BytecodeFormat::GlobalTypePlane, Out);

    // Write the type plane for types first because earlier planes (e.g. for a
    // primitive type like float) may have constants constructed using types
    // coming later (e.g., via getelementptr from a pointer type).  The type
    // plane is needed before types can be fwd or bkwd referenced.
    const std::vector<const Value*> &Plane = Table.getPlane(Type::TypeTyID);
    assert(!Plane.empty() && "No types at all?");
    unsigned ValNo = Type::FirstDerivedTyID; // Start at the derived types...
    outputConstantsInPlane(Plane, ValNo);      // Write out the types
  }

  // The ModuleInfoBlock follows directly after the type information
  outputModuleInfoBlock(M);

  // Output module level constants, used for global variable initializers
  outputConstants(false);

  // Do the whole module now! Process each function at a time...
  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
    outputFunction(I);

  // If needed, output the symbol table for the module...
  outputSymbolTable(M->getSymbolTable());
}

// Helper function for outputConstants().
// Writes out all the constants in the plane Plane starting at entry StartNo.
//
void BytecodeWriter::outputConstantsInPlane(const std::vector<const Value*>
                                            &Plane, unsigned StartNo) {
  unsigned ValNo = StartNo;

  // Scan through and ignore function arguments, global values, and constant
  // strings.
  for (; ValNo < Plane.size() &&
         (isa<Argument>(Plane[ValNo]) || isa<GlobalValue>(Plane[ValNo]) ||
          (isa<ConstantArray>(Plane[ValNo]) &&
           cast<ConstantArray>(Plane[ValNo])->isString())); ValNo++)
    /*empty*/;

  unsigned NC = ValNo;              // Number of constants
  for (; NC < Plane.size() &&
         (isa<Constant>(Plane[NC]) || isa<Type>(Plane[NC])); NC++)
    /*empty*/;
  NC -= ValNo;                      // Convert from index into count
  if (NC == 0) return;              // Skip empty type planes...

  // FIXME: Most slabs only have 1 or 2 entries!  We should encode this much
  // more compactly.

  // Output type header: [num entries][type id number]
  //
  output_vbr(NC, Out);

  // Output the Type ID Number...
  int Slot = Table.getSlot(Plane.front()->getType());
  assert (Slot != -1 && "Type in constant pool but not in function!!");
  output_vbr((unsigned)Slot, Out);

  //cerr << "Emitting " << NC << " constants of type '"
  //	 << Plane.front()->getType()->getName() << "' = Slot #" << Slot << "\n";

  for (unsigned i = ValNo; i < ValNo+NC; ++i) {
    const Value *V = Plane[i];
    if (const Constant *CPV = dyn_cast<Constant>(V)) {
      //cerr << "Serializing value: <" << V->getType() << ">: " << V << ":"
      //     << Out.size() << "\n";
      outputConstant(CPV);
    } else {
      outputType(cast<Type>(V));
    }
  }
}

static inline bool hasNullValue(unsigned TyID) {
  return TyID != Type::LabelTyID && TyID != Type::TypeTyID &&
         TyID != Type::VoidTyID;
}

void BytecodeWriter::outputConstants(bool isFunction) {
  BytecodeBlock CPool(BytecodeFormat::ConstantPool, Out,
                      true  /* Elide block if empty */);

  unsigned NumPlanes = Table.getNumPlanes();

  // Output the type plane before any constants!
  if (isFunction && NumPlanes > Type::TypeTyID) {
    const std::vector<const Value*> &Plane = Table.getPlane(Type::TypeTyID);
    if (!Plane.empty()) {              // Skip empty type planes...
      unsigned ValNo = Table.getModuleLevel(Type::TypeTyID);
      outputConstantsInPlane(Plane, ValNo);
    }
  }

  // Output module-level string constants before any other constants.x
  if (!isFunction)
    outputConstantStrings();

  for (unsigned pno = 0; pno != NumPlanes; pno++)
    if (pno != Type::TypeTyID) {         // Type plane handled above.
      const std::vector<const Value*> &Plane = Table.getPlane(pno);
      if (!Plane.empty()) {              // Skip empty type planes...
        unsigned ValNo = 0;
        if (isFunction)                  // Don't re-emit module constants
          ValNo += Table.getModuleLevel(pno);

        if (hasNullValue(pno)) {
          // Skip zero initializer
          if (ValNo == 0)
            ValNo = 1;
        }

        // Write out constants in the plane
        outputConstantsInPlane(Plane, ValNo);
      }
    }
}

static unsigned getEncodedLinkage(const GlobalValue *GV) {
  switch (GV->getLinkage()) {
  default: assert(0 && "Invalid linkage!");
  case GlobalValue::ExternalLinkage:  return 0;
  case GlobalValue::WeakLinkage:      return 1;
  case GlobalValue::AppendingLinkage: return 2;
  case GlobalValue::InternalLinkage:  return 3;
  case GlobalValue::LinkOnceLinkage:  return 4;
  }
}

void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
  BytecodeBlock ModuleInfoBlock(BytecodeFormat::ModuleGlobalInfo, Out);

  // Output the types for the global variables in the module...
  for (Module::const_giterator I = M->gbegin(), End = M->gend(); I != End;++I) {
    int Slot = Table.getSlot(I->getType());
    assert(Slot != -1 && "Module global vars is broken!");

    // Fields: bit0 = isConstant, bit1 = hasInitializer, bit2-4=Linkage,
    // bit5+ = Slot # for type
    unsigned oSlot = ((unsigned)Slot << 5) | (getEncodedLinkage(I) << 2) |
                     (I->hasInitializer() << 1) | I->isConstant();
    output_vbr(oSlot, Out);

    // If we have an initializer, output it now.
    if (I->hasInitializer()) {
      Slot = Table.getSlot((Value*)I->getInitializer());
      assert(Slot != -1 && "No slot for global var initializer!");
      output_vbr((unsigned)Slot, Out);
    }
  }
  output_vbr((unsigned)Table.getSlot(Type::VoidTy), Out);

  // Output the types of the functions in this module...
  for (Module::const_iterator I = M->begin(), End = M->end(); I != End; ++I) {
    int Slot = Table.getSlot(I->getType());
    assert(Slot != -1 && "Module const pool is broken!");
    assert(Slot >= Type::FirstDerivedTyID && "Derived type not in range!");
    output_vbr((unsigned)Slot, Out);
  }
  output_vbr((unsigned)Table.getSlot(Type::VoidTy), Out);
}

void BytecodeWriter::outputInstructions(const Function *F) {
  BytecodeBlock ILBlock(BytecodeFormat::InstructionList, Out);
  for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
    for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I)
      outputInstruction(*I);
}

void BytecodeWriter::outputFunction(const Function *F) {
  BytecodeBlock FunctionBlock(BytecodeFormat::Function, Out);
  output_vbr(getEncodedLinkage(F), Out);

  // If this is an external function, there is nothing else to emit!
  if (F->isExternal()) return;

  // Get slot information about the function...
  Table.incorporateFunction(F);

  if (Table.getCompactionTable().empty()) {
    // Output information about the constants in the function if the compaction
    // table is not being used.
    outputConstants(true);
  } else {
    // Otherwise, emit the compaction table.
    outputCompactionTable();
  }

  // Output all of the instructions in the body of the function
  outputInstructions(F);

  // If needed, output the symbol table for the function...
  outputSymbolTable(F->getSymbolTable());

  Table.purgeFunction();
}

void BytecodeWriter::outputCompactionTablePlane(unsigned PlaneNo,
                                         const std::vector<const Value*> &Plane,
                                                unsigned StartNo) {
  unsigned End = Table.getModuleLevel(PlaneNo);
  if (Plane.empty() || StartNo == End || End == 0) return;   // Nothing to emit
  assert(StartNo < End && "Cannot emit negative range!");
  assert(StartNo < Plane.size() && End <= Plane.size());

  // Do not emit the null initializer!
  if (PlaneNo != Type::TypeTyID) ++StartNo;

  // Figure out which encoding to use.  By far the most common case we have is
  // to emit 0-2 entries in a compaction table plane.
  switch (End-StartNo) {
  case 0:         // Avoid emitting two vbr's if possible.
  case 1:
  case 2:
    output_vbr((PlaneNo << 2) | End-StartNo, Out);
    break;
  default:
    // Output the number of things.
    output_vbr((unsigned(End-StartNo) << 2) | 3, Out);
    output_vbr(PlaneNo, Out);                 // Emit the type plane this is
    break;
  }

  for (unsigned i = StartNo; i != End; ++i)
    output_vbr(Table.getGlobalSlot(Plane[i]), Out);
}

void BytecodeWriter::outputCompactionTable() {
  BytecodeBlock CTB(BytecodeFormat::CompactionTable, Out, true/*ElideIfEmpty*/);
  const std::vector<std::vector<const Value*> > &CT =Table.getCompactionTable();

  // First thing is first, emit the type compaction table if there is one.
  if (CT.size() > Type::TypeTyID)
    outputCompactionTablePlane(Type::TypeTyID, CT[Type::TypeTyID],
                               Type::FirstDerivedTyID);

  for (unsigned i = 0, e = CT.size(); i != e; ++i)
    if (i != Type::TypeTyID)
      outputCompactionTablePlane(i, CT[i], 0);
}

void BytecodeWriter::outputSymbolTable(const SymbolTable &MST) {
  // Do not output the Bytecode block for an empty symbol table, it just wastes
  // space!
  if (MST.begin() == MST.end()) return;

  BytecodeBlock SymTabBlock(BytecodeFormat::SymbolTable, Out,
                            true/* ElideIfEmpty*/);

  for (SymbolTable::const_iterator TI = MST.begin(); TI != MST.end(); ++TI) {
    SymbolTable::type_const_iterator I = MST.type_begin(TI->first);
    SymbolTable::type_const_iterator End = MST.type_end(TI->first);
    int Slot;

    if (I == End) continue;  // Don't mess with an absent type...

    // Symtab block header: [num entries][type id number]
    output_vbr(MST.type_size(TI->first), Out);

    Slot = Table.getSlot(TI->first);
    assert(Slot != -1 && "Type in symtab, but not in table!");
    output_vbr((unsigned)Slot, Out);

    for (; I != End; ++I) {
      // Symtab entry: [def slot #][name]
      const Value *V = I->second;

      Slot = Table.getSlot(I->second);
      assert(Slot != -1 && "Value in symtab but has no slot number!!");
      output_vbr((unsigned)Slot, Out);
      output(I->first, Out, false); // Don't force alignment...
    }
  }
}

void llvm::WriteBytecodeToFile(const Module *C, std::ostream &Out) {
  assert(C && "You can't write a null module!!");

  std::deque<unsigned char> Buffer;

  // This object populates buffer for us...
  BytecodeWriter BCW(Buffer, C);

  // Keep track of how much we've written...
  BytesWritten += Buffer.size();

  // Okay, write the deque out to the ostream now... the deque is not
  // sequential in memory, however, so write out as much as possible in big
  // chunks, until we're done.
  //
  std::deque<unsigned char>::const_iterator I = Buffer.begin(),E = Buffer.end();
  while (I != E) {                           // Loop until it's all written
    // Scan to see how big this chunk is...
    const unsigned char *ChunkPtr = &*I;
    const unsigned char *LastPtr = ChunkPtr;
    while (I != E) {
      const unsigned char *ThisPtr = &*++I;
      if (LastPtr+1 != ThisPtr) {   // Advanced by more than a byte of memory?
        ++LastPtr;
        break;
      }
      LastPtr = ThisPtr;
    }

    // Write out the chunk...
    Out.write((char*)ChunkPtr, LastPtr-ChunkPtr);
  }

  Out.flush();
}
<commit_msg>Changed to use SymbolTable's new iteration interfaces.<commit_after>//===-- Writer.cpp - Library for writing LLVM bytecode files --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This library implements the functionality defined in llvm/Bytecode/Writer.h
//
// Note that this file uses an unusual technique of outputting all the bytecode
// to a deque of unsigned char, then copies the deque to an ostream.  The
// reason for this is that we must do "seeking" in the stream to do back-
// patching, and some very important ostreams that we want to support (like
// pipes) do not support seeking.  :( :( :(
//
// The choice of the deque data structure is influenced by the extremely fast
// "append" speed, plus the free "seek"/replace in the middle of the stream. I
// didn't use a vector because the stream could end up very large and copying
// the whole thing to reallocate would be kinda silly.
//
//===----------------------------------------------------------------------===//

#include "WriterInternals.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include "Support/STLExtras.h"
#include "Support/Statistic.h"
#include <cstring>
#include <algorithm>
using namespace llvm;

static RegisterPass<WriteBytecodePass> X("emitbytecode", "Bytecode Writer");

static Statistic<>
BytesWritten("bytecodewriter", "Number of bytecode bytes written");

BytecodeWriter::BytecodeWriter(std::deque<unsigned char> &o, const Module *M)
  : Out(o), Table(M, true) {

  // Emit the signature...
  static const unsigned char *Sig =  (const unsigned char*)"llvm";
  output_data(Sig, Sig+4, Out);

  // Emit the top level CLASS block.
  BytecodeBlock ModuleBlock(BytecodeFormat::Module, Out);

  bool isBigEndian      = M->getEndianness() == Module::BigEndian;
  bool hasLongPointers  = M->getPointerSize() == Module::Pointer64;
  bool hasNoEndianness  = M->getEndianness() == Module::AnyEndianness;
  bool hasNoPointerSize = M->getPointerSize() == Module::AnyPointerSize;

  // Output the version identifier... we are currently on bytecode version #2,
  // which corresponds to LLVM v1.3.
  unsigned Version = (2 << 4) | isBigEndian | (hasLongPointers << 1) |
                     (hasNoEndianness << 2) | (hasNoPointerSize << 3);
  output_vbr(Version, Out);
  align32(Out);

  {
    BytecodeBlock CPool(BytecodeFormat::GlobalTypePlane, Out);

    // Write the type plane for types first because earlier planes (e.g. for a
    // primitive type like float) may have constants constructed using types
    // coming later (e.g., via getelementptr from a pointer type).  The type
    // plane is needed before types can be fwd or bkwd referenced.
    const std::vector<const Value*> &Plane = Table.getPlane(Type::TypeTyID);
    assert(!Plane.empty() && "No types at all?");
    unsigned ValNo = Type::FirstDerivedTyID; // Start at the derived types...
    outputConstantsInPlane(Plane, ValNo);      // Write out the types
  }

  // The ModuleInfoBlock follows directly after the type information
  outputModuleInfoBlock(M);

  // Output module level constants, used for global variable initializers
  outputConstants(false);

  // Do the whole module now! Process each function at a time...
  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
    outputFunction(I);

  // If needed, output the symbol table for the module...
  outputSymbolTable(M->getSymbolTable());
}

// Helper function for outputConstants().
// Writes out all the constants in the plane Plane starting at entry StartNo.
//
void BytecodeWriter::outputConstantsInPlane(const std::vector<const Value*>
                                            &Plane, unsigned StartNo) {
  unsigned ValNo = StartNo;

  // Scan through and ignore function arguments, global values, and constant
  // strings.
  for (; ValNo < Plane.size() &&
         (isa<Argument>(Plane[ValNo]) || isa<GlobalValue>(Plane[ValNo]) ||
          (isa<ConstantArray>(Plane[ValNo]) &&
           cast<ConstantArray>(Plane[ValNo])->isString())); ValNo++)
    /*empty*/;

  unsigned NC = ValNo;              // Number of constants
  for (; NC < Plane.size() &&
         (isa<Constant>(Plane[NC]) || isa<Type>(Plane[NC])); NC++)
    /*empty*/;
  NC -= ValNo;                      // Convert from index into count
  if (NC == 0) return;              // Skip empty type planes...

  // FIXME: Most slabs only have 1 or 2 entries!  We should encode this much
  // more compactly.

  // Output type header: [num entries][type id number]
  //
  output_vbr(NC, Out);

  // Output the Type ID Number...
  int Slot = Table.getSlot(Plane.front()->getType());
  assert (Slot != -1 && "Type in constant pool but not in function!!");
  output_vbr((unsigned)Slot, Out);

  //cerr << "Emitting " << NC << " constants of type '"
  //	 << Plane.front()->getType()->getName() << "' = Slot #" << Slot << "\n";

  for (unsigned i = ValNo; i < ValNo+NC; ++i) {
    const Value *V = Plane[i];
    if (const Constant *CPV = dyn_cast<Constant>(V)) {
      //cerr << "Serializing value: <" << V->getType() << ">: " << V << ":"
      //     << Out.size() << "\n";
      outputConstant(CPV);
    } else {
      outputType(cast<Type>(V));
    }
  }
}

static inline bool hasNullValue(unsigned TyID) {
  return TyID != Type::LabelTyID && TyID != Type::TypeTyID &&
         TyID != Type::VoidTyID;
}

void BytecodeWriter::outputConstants(bool isFunction) {
  BytecodeBlock CPool(BytecodeFormat::ConstantPool, Out,
                      true  /* Elide block if empty */);

  unsigned NumPlanes = Table.getNumPlanes();

  // Output the type plane before any constants!
  if (isFunction && NumPlanes > Type::TypeTyID) {
    const std::vector<const Value*> &Plane = Table.getPlane(Type::TypeTyID);
    if (!Plane.empty()) {              // Skip empty type planes...
      unsigned ValNo = Table.getModuleLevel(Type::TypeTyID);
      outputConstantsInPlane(Plane, ValNo);
    }
  }

  // Output module-level string constants before any other constants.x
  if (!isFunction)
    outputConstantStrings();

  for (unsigned pno = 0; pno != NumPlanes; pno++)
    if (pno != Type::TypeTyID) {         // Type plane handled above.
      const std::vector<const Value*> &Plane = Table.getPlane(pno);
      if (!Plane.empty()) {              // Skip empty type planes...
        unsigned ValNo = 0;
        if (isFunction)                  // Don't re-emit module constants
          ValNo += Table.getModuleLevel(pno);

        if (hasNullValue(pno)) {
          // Skip zero initializer
          if (ValNo == 0)
            ValNo = 1;
        }

        // Write out constants in the plane
        outputConstantsInPlane(Plane, ValNo);
      }
    }
}

static unsigned getEncodedLinkage(const GlobalValue *GV) {
  switch (GV->getLinkage()) {
  default: assert(0 && "Invalid linkage!");
  case GlobalValue::ExternalLinkage:  return 0;
  case GlobalValue::WeakLinkage:      return 1;
  case GlobalValue::AppendingLinkage: return 2;
  case GlobalValue::InternalLinkage:  return 3;
  case GlobalValue::LinkOnceLinkage:  return 4;
  }
}

void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
  BytecodeBlock ModuleInfoBlock(BytecodeFormat::ModuleGlobalInfo, Out);

  // Output the types for the global variables in the module...
  for (Module::const_giterator I = M->gbegin(), End = M->gend(); I != End;++I) {
    int Slot = Table.getSlot(I->getType());
    assert(Slot != -1 && "Module global vars is broken!");

    // Fields: bit0 = isConstant, bit1 = hasInitializer, bit2-4=Linkage,
    // bit5+ = Slot # for type
    unsigned oSlot = ((unsigned)Slot << 5) | (getEncodedLinkage(I) << 2) |
                     (I->hasInitializer() << 1) | I->isConstant();
    output_vbr(oSlot, Out);

    // If we have an initializer, output it now.
    if (I->hasInitializer()) {
      Slot = Table.getSlot((Value*)I->getInitializer());
      assert(Slot != -1 && "No slot for global var initializer!");
      output_vbr((unsigned)Slot, Out);
    }
  }
  output_vbr((unsigned)Table.getSlot(Type::VoidTy), Out);

  // Output the types of the functions in this module...
  for (Module::const_iterator I = M->begin(), End = M->end(); I != End; ++I) {
    int Slot = Table.getSlot(I->getType());
    assert(Slot != -1 && "Module const pool is broken!");
    assert(Slot >= Type::FirstDerivedTyID && "Derived type not in range!");
    output_vbr((unsigned)Slot, Out);
  }
  output_vbr((unsigned)Table.getSlot(Type::VoidTy), Out);
}

void BytecodeWriter::outputInstructions(const Function *F) {
  BytecodeBlock ILBlock(BytecodeFormat::InstructionList, Out);
  for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
    for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I)
      outputInstruction(*I);
}

void BytecodeWriter::outputFunction(const Function *F) {
  BytecodeBlock FunctionBlock(BytecodeFormat::Function, Out);
  output_vbr(getEncodedLinkage(F), Out);

  // If this is an external function, there is nothing else to emit!
  if (F->isExternal()) return;

  // Get slot information about the function...
  Table.incorporateFunction(F);

  if (Table.getCompactionTable().empty()) {
    // Output information about the constants in the function if the compaction
    // table is not being used.
    outputConstants(true);
  } else {
    // Otherwise, emit the compaction table.
    outputCompactionTable();
  }

  // Output all of the instructions in the body of the function
  outputInstructions(F);

  // If needed, output the symbol table for the function...
  outputSymbolTable(F->getSymbolTable());

  Table.purgeFunction();
}

void BytecodeWriter::outputCompactionTablePlane(unsigned PlaneNo,
                                         const std::vector<const Value*> &Plane,
                                                unsigned StartNo) {
  unsigned End = Table.getModuleLevel(PlaneNo);
  if (Plane.empty() || StartNo == End || End == 0) return;   // Nothing to emit
  assert(StartNo < End && "Cannot emit negative range!");
  assert(StartNo < Plane.size() && End <= Plane.size());

  // Do not emit the null initializer!
  if (PlaneNo != Type::TypeTyID) ++StartNo;

  // Figure out which encoding to use.  By far the most common case we have is
  // to emit 0-2 entries in a compaction table plane.
  switch (End-StartNo) {
  case 0:         // Avoid emitting two vbr's if possible.
  case 1:
  case 2:
    output_vbr((PlaneNo << 2) | End-StartNo, Out);
    break;
  default:
    // Output the number of things.
    output_vbr((unsigned(End-StartNo) << 2) | 3, Out);
    output_vbr(PlaneNo, Out);                 // Emit the type plane this is
    break;
  }

  for (unsigned i = StartNo; i != End; ++i)
    output_vbr(Table.getGlobalSlot(Plane[i]), Out);
}

void BytecodeWriter::outputCompactionTable() {
  BytecodeBlock CTB(BytecodeFormat::CompactionTable, Out, true/*ElideIfEmpty*/);
  const std::vector<std::vector<const Value*> > &CT =Table.getCompactionTable();

  // First thing is first, emit the type compaction table if there is one.
  if (CT.size() > Type::TypeTyID)
    outputCompactionTablePlane(Type::TypeTyID, CT[Type::TypeTyID],
                               Type::FirstDerivedTyID);

  for (unsigned i = 0, e = CT.size(); i != e; ++i)
    if (i != Type::TypeTyID)
      outputCompactionTablePlane(i, CT[i], 0);
}

void BytecodeWriter::outputSymbolTable(const SymbolTable &MST) {
  // Do not output the Bytecode block for an empty symbol table, it just wastes
  // space!
  if (MST.plane_begin() == MST.plane_end()) return;

  BytecodeBlock SymTabBlock(BytecodeFormat::SymbolTable, Out,
                            true/* ElideIfEmpty*/);

  //Symtab block header: [num entries][type id number]
  output_vbr(MST.num_types(), Out);
  output_vbr((unsigned)Table.getSlot(Type::TypeTy), Out);
  for (SymbolTable::type_const_iterator TI = MST.type_begin(),
       TE = MST.type_end(); TI != TE; ++TI ) {
    //Symtab entry:[def slot #][name]
    output_vbr((unsigned)Table.getSlot(TI->second), Out);
    output(TI->first, Out, /*align=*/false);
  }

  // Now do each of the type planes in order.
  for (SymbolTable::plane_const_iterator PI = MST.plane_begin(),
       PE = MST.plane_end(); PI != PE;  ++PI) {
    SymbolTable::value_const_iterator I = MST.value_begin(PI->first);
    SymbolTable::value_const_iterator End = MST.value_end(PI->first);
    int Slot;

    if (I == End) continue;  // Don't mess with an absent type...

    // Symtab block header: [num entries][type id number]
    output_vbr(MST.type_size(PI->first), Out);

    Slot = Table.getSlot(PI->first);
    assert(Slot != -1 && "Type in symtab, but not in table!");
    output_vbr((unsigned)Slot, Out);

    for (; I != End; ++I) {
      // Symtab entry: [def slot #][name]
      const Value *V = I->second;

      Slot = Table.getSlot(I->second);
      assert(Slot != -1 && "Value in symtab but has no slot number!!");
      output_vbr((unsigned)Slot, Out);
      output(I->first, Out, false); // Don't force alignment...
    }
  }
}

void llvm::WriteBytecodeToFile(const Module *C, std::ostream &Out) {
  assert(C && "You can't write a null module!!");

  std::deque<unsigned char> Buffer;

  // This object populates buffer for us...
  BytecodeWriter BCW(Buffer, C);

  // Keep track of how much we've written...
  BytesWritten += Buffer.size();

  // Okay, write the deque out to the ostream now... the deque is not
  // sequential in memory, however, so write out as much as possible in big
  // chunks, until we're done.
  //
  std::deque<unsigned char>::const_iterator I = Buffer.begin(),E = Buffer.end();
  while (I != E) {                           // Loop until it's all written
    // Scan to see how big this chunk is...
    const unsigned char *ChunkPtr = &*I;
    const unsigned char *LastPtr = ChunkPtr;
    while (I != E) {
      const unsigned char *ThisPtr = &*++I;
      if (LastPtr+1 != ThisPtr) {   // Advanced by more than a byte of memory?
        ++LastPtr;
        break;
      }
      LastPtr = ThisPtr;
    }

    // Write out the chunk...
    Out.write((char*)ChunkPtr, LastPtr-ChunkPtr);
  }

  Out.flush();
}
<|endoftext|>


<commit_before><commit_msg>better error message<commit_after><|endoftext|>


<commit_before><commit_msg>Don't trim whitespace while parsing xml<commit_after><|endoftext|>


<commit_before>/////////////////////////////////////////
//
//         LieroX Game Script Compiler
//
//     Copyright Auxiliary Software 2002
//
//
/////////////////////////////////////////

// OpenLieroX
// code under LGPL

// Main compiler
// Created 7/2/02
// Jason Boettcher

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include "CVec.h"
#include "CGameScript.h"
#include "ConfigHandler.h"
#include "SmartPointer.h"
#include "CrashHandler.h"

// Prototypes
int		CheckArgs(int argc, char *argv[]);

///////////////////
// Main entry point
int main(int argc, char *argv[])
{
	notes << "Liero Xtreme Game Script Compiler" << endl;
	notes << "(c) ..-2002  Auxiliary Software " << endl;
	notes << "    2002-..  OpenLieroX team" << endl;
	notes << "Version: " << GetGameVersion().asString() << endl;
	notes << "GameScript Version: " << GS_VERSION << endl << endl << endl;

	if( !CheckArgs(argc, argv) ) {
		return 1;
	}

	CGameScript	*Game = new CGameScript;
	if(Game == NULL) {
		errors << "GameCompiler: Out of memory while creating gamescript" << endl;
		return false;
	}

	// Compile
	bool comp = Game->Compile(argv[1]);

	// Only save if the compile went ok
	if(comp) {
		printf("\nSaving...\n");
		Game->Save(argv[2]);
	}

	if(comp)
		printf("\nInfo:\nWeapons: %d\nProjectiles: %d\n",Game->GetNumWeapons(),Game->getProjectileCount());

	if(Game) {
		delete Game;
		Game = NULL;
	}

	return 0;
}

///////////////////
// Check the arguments
int CheckArgs(int argc, char *argv[])
{
	char *d = strrchr(argv[0],'\\');
	if(!d)
		d = argv[0];
	else
		d++;

	if(argc != 3) {
		printf("Usage:\n");
		printf("%s [Mod dir] [filename]\n",d);
		printf("\nExample:\n");
		printf("%s Base script.lgs\n\n",d);
		return false;
	}

	return true;
}

// some dummies/stubs are following to be able to compile with OLX sources

FILE* OpenGameFile(const std::string& file, const char* mod) {
	// stub
	return fopen(file.c_str(), mod);
}

bool GetExactFileName(const std::string& fn, std::string& exactfn) {
	// sub
	exactfn = fn;
	return true;
}

struct SoundSample;
template <> void SmartPointer_ObjectDeinit<SoundSample> ( SoundSample * obj )
{
	errors << "SmartPointer_ObjectDeinit SoundSample: stub" << endl;
}

template <> void SmartPointer_ObjectDeinit<SDL_Surface> ( SDL_Surface * obj )
{
	errors << "SmartPointer_ObjectDeinit SDL_Surface: stub" << endl;
}

SmartPointer<SoundSample> LoadSample(const std::string& _filename, int maxplaying) {
	// stub
	return NULL;
}

SmartPointer<SDL_Surface> LoadGameImage(const std::string& _filename, bool withalpha) {
	// stub
	return NULL;
}

void SetColorKey(SDL_Surface * dst) {} // stub

bool bDedicated = true;

void SetError(const std::string& text) { errors << "SetError: " << text << endl; }

struct GameOptions;
GameOptions *tLXOptions = NULL;

bool Con_IsInited() { return false; }

CrashHandler* CrashHandler::get() {	return NULL; }

void Con_AddText(int colour, const std::string& text, bool alsoToLogger) {}

SDL_PixelFormat defaultFallbackFormat =
{
 NULL, //SDL_Palette *palette;
 32, //Uint8  BitsPerPixel;
 4, //Uint8  BytesPerPixel;
 0, 0, 0, 0, //Uint8  Rloss, Gloss, Bloss, Aloss;
 24, 16, 8, 0, //Uint8  Rshift, Gshift, Bshift, Ashift;
 0xff000000, 0xff0000, 0xff00, 0xff, //Uint32 Rmask, Gmask, Bmask, Amask;
 0, //Uint32 colorkey;
 255 //Uint8  alpha;
};

SDL_PixelFormat* mainPixelFormat = &defaultFallbackFormat;
<commit_msg>better output<commit_after>/////////////////////////////////////////
//
//         LieroX Game Script Compiler
//
//     Copyright Auxiliary Software 2002
//
//
/////////////////////////////////////////

// OpenLieroX
// code under LGPL

// Main compiler
// Created 7/2/02
// Jason Boettcher

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include "CVec.h"
#include "CGameScript.h"
#include "ConfigHandler.h"
#include "SmartPointer.h"
#include "CrashHandler.h"

// Prototypes
int		CheckArgs(int argc, char *argv[]);

///////////////////
// Main entry point
int main(int argc, char *argv[])
{
	notes << "Liero Xtreme Game Script Compiler" << endl;
	notes << "(c) ..-2002  Auxiliary Software " << endl;
	notes << "    2002-..  OpenLieroX team" << endl;
	notes << "Version: " << GetGameVersion().asString() << endl;
	notes << "GameScript Version: " << GS_VERSION << endl << endl << endl;

	if( !CheckArgs(argc, argv) ) {
		return 1;
	}

	CGameScript	*Game = new CGameScript;
	if(Game == NULL) {
		errors << "GameCompiler: Out of memory while creating gamescript" << endl;
		return false;
	}

	// Compile
	bool comp = Game->Compile(argv[1]);

	// Only save if the compile went ok
	if(comp) {
		notes << endl << "Saving..." << endl;
		Game->Save(argv[2]);
	}

	if(comp)
		notes << endl <<
				"Info:" << endl <<
				"Weapons: " << Game->GetNumWeapons() << endl <<
				"Projectiles: " << Game->getProjectileCount() << endl;

	if(Game) {
		delete Game;
		Game = NULL;
	}

	return 0;
}

///////////////////
// Check the arguments
int CheckArgs(int argc, char *argv[])
{
	char *d = strrchr(argv[0],'\\');
	if(!d)
		d = argv[0];
	else
		d++;

	if(argc != 3) {
		notes << "Usage:" << endl;
		notes << d << " [Mod dir] [filename]" << endl;
		notes << endl << "Example:" << endl;
		notes << d << " Base script.lgs" << endl << endl;
		return false;
	}

	return true;
}

// some dummies/stubs are following to be able to compile with OLX sources

FILE* OpenGameFile(const std::string& file, const char* mod) {
	// stub
	return fopen(file.c_str(), mod);
}

bool GetExactFileName(const std::string& fn, std::string& exactfn) {
	// sub
	exactfn = fn;
	return true;
}

struct SoundSample;
template <> void SmartPointer_ObjectDeinit<SoundSample> ( SoundSample * obj )
{
	errors << "SmartPointer_ObjectDeinit SoundSample: stub" << endl;
}

template <> void SmartPointer_ObjectDeinit<SDL_Surface> ( SDL_Surface * obj )
{
	errors << "SmartPointer_ObjectDeinit SDL_Surface: stub" << endl;
}

SmartPointer<SoundSample> LoadSample(const std::string& _filename, int maxplaying) {
	// stub
	return NULL;
}

SmartPointer<SDL_Surface> LoadGameImage(const std::string& _filename, bool withalpha) {
	// stub
	return NULL;
}

void SetColorKey(SDL_Surface * dst) {} // stub

bool bDedicated = true;

void SetError(const std::string& text) { errors << "SetError: " << text << endl; }

struct GameOptions;
GameOptions *tLXOptions = NULL;

bool Con_IsInited() { return false; }

CrashHandler* CrashHandler::get() {	return NULL; }

void Con_AddText(int colour, const std::string& text, bool alsoToLogger) {}

SDL_PixelFormat defaultFallbackFormat =
{
 NULL, //SDL_Palette *palette;
 32, //Uint8  BitsPerPixel;
 4, //Uint8  BytesPerPixel;
 0, 0, 0, 0, //Uint8  Rloss, Gloss, Bloss, Aloss;
 24, 16, 8, 0, //Uint8  Rshift, Gshift, Bshift, Ashift;
 0xff000000, 0xff0000, 0xff00, 0xff, //Uint32 Rmask, Gmask, Bmask, Amask;
 0, //Uint32 colorkey;
 255 //Uint8  alpha;
};

SDL_PixelFormat* mainPixelFormat = &defaultFallbackFormat;
<|endoftext|>


<commit_before><commit_msg>mention the -directory option if no fonts are found<commit_after><|endoftext|>


<commit_before>//===-- PhiElimination.cpp - Eliminate PHI nodes by inserting copies ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass eliminates machine instruction PHI nodes by inserting copy
// instructions.  This destroys SSA information, but is the desired input for
// some register allocators.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include <set>
using namespace llvm;

namespace {
  struct PNE : public MachineFunctionPass {
    bool runOnMachineFunction(MachineFunction &Fn) {
      bool Changed = false;

      // Eliminate PHI instructions by inserting copies into predecessor blocks.
      for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
        Changed |= EliminatePHINodes(Fn, *I);

      return Changed;
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<LiveVariables>();
      MachineFunctionPass::getAnalysisUsage(AU);
    }

  private:
    /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions
    /// in predecessor basic blocks.
    ///
    bool EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB);
    void LowerAtomicPHINode(MachineBasicBlock &MBB,
                            MachineBasicBlock::iterator AfterPHIsIt,
                            DenseMap<unsigned, VirtReg2IndexFunctor> &VUC,
                            unsigned BBIsSuccOfPreds);
  };

  RegisterPass<PNE> X("phi-node-elimination",
                      "Eliminate PHI nodes for register allocation");
}

const PassInfo *llvm::PHIEliminationID = X.getPassInfo();

/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
/// predecessor basic blocks.
///
bool PNE::EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB) {
  if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI)
    return false;   // Quick exit for basic blocks without PHIs.

  // VRegPHIUseCount - Keep track of the number of times each virtual register
  // is used by PHI nodes in successors of this block.
  DenseMap<unsigned, VirtReg2IndexFunctor> VRegPHIUseCount;
  VRegPHIUseCount.grow(MF.getSSARegMap()->getLastVirtReg());

  unsigned BBIsSuccOfPreds = 0;  // Number of times MBB is a succ of preds
  for (MachineBasicBlock::pred_iterator PI = MBB.pred_begin(),
         E = MBB.pred_end(); PI != E; ++PI)
    for (MachineBasicBlock::succ_iterator SI = (*PI)->succ_begin(),
           E = (*PI)->succ_end(); SI != E; ++SI) {
    BBIsSuccOfPreds += *SI == &MBB;
    for (MachineBasicBlock::iterator BBI = (*SI)->begin(); BBI !=(*SI)->end() &&
           BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI)
      for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2)
        VRegPHIUseCount[BBI->getOperand(i).getReg()]++;
  }

  // Get an iterator to the first instruction after the last PHI node (this may
  // also be the end of the basic block).
  MachineBasicBlock::iterator AfterPHIsIt = MBB.begin();
  while (AfterPHIsIt != MBB.end() &&
         AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI)
    ++AfterPHIsIt;    // Skip over all of the PHI nodes...

  while (MBB.front().getOpcode() == TargetInstrInfo::PHI) {
    LowerAtomicPHINode(MBB, AfterPHIsIt, VRegPHIUseCount, BBIsSuccOfPreds);
  }
  return true;
}

/// LowerAtomicPHINode - Lower the PHI node at the top of the specified block,
/// under the assuption that it needs to be lowered in a way that supports
/// atomic execution of PHIs.  This lowering method is always correct all of the
/// time.
void PNE::LowerAtomicPHINode(MachineBasicBlock &MBB,
                             MachineBasicBlock::iterator AfterPHIsIt,
                      DenseMap<unsigned, VirtReg2IndexFunctor> &VRegPHIUseCount,
                             unsigned BBIsSuccOfPreds) {
  // Unlink the PHI node from the basic block, but don't delete the PHI yet.
  MachineInstr *MPhi = MBB.remove(MBB.begin());

  unsigned DestReg = MPhi->getOperand(0).getReg();

  // Create a new register for the incoming PHI arguments/
  MachineFunction &MF = *MBB.getParent();
  const TargetRegisterClass *RC = MF.getSSARegMap()->getRegClass(DestReg);
  unsigned IncomingReg = MF.getSSARegMap()->createVirtualRegister(RC);

  // Insert a register to register copy in the top of the current block (but
  // after any remaining phi nodes) which copies the new incoming register
  // into the phi node destination.
  //
  const MRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
  RegInfo->copyRegToReg(MBB, AfterPHIsIt, DestReg, IncomingReg, RC);

  // Update live variable information if there is any...
  LiveVariables *LV = getAnalysisToUpdate<LiveVariables>();
  if (LV) {
    MachineInstr *PHICopy = prior(AfterPHIsIt);

    // Add information to LiveVariables to know that the incoming value is
    // killed.  Note that because the value is defined in several places (once
    // each for each incoming block), the "def" block and instruction fields
    // for the VarInfo is not filled in.
    //
    LV->addVirtualRegisterKilled(IncomingReg, PHICopy);

    // Since we are going to be deleting the PHI node, if it is the last use
    // of any registers, or if the value itself is dead, we need to move this
    // information over to the new copy we just inserted.
    //
    LV->removeVirtualRegistersKilled(MPhi);

    std::pair<LiveVariables::killed_iterator, LiveVariables::killed_iterator>
      RKs = LV->dead_range(MPhi);
    if (RKs.first != RKs.second) {
      for (LiveVariables::killed_iterator I = RKs.first; I != RKs.second; ++I)
        LV->addVirtualRegisterDead(*I, PHICopy);
      LV->removeVirtualRegistersDead(MPhi);
    }
  }

  // Adjust the VRegPHIUseCount map to account for the removal of this PHI
  // node.
  for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2)
    VRegPHIUseCount[MPhi->getOperand(i).getReg()] -= BBIsSuccOfPreds;

  // Now loop over all of the incoming arguments, changing them to copy into
  // the IncomingReg register in the corresponding predecessor basic block.
  //
  for (int i = MPhi->getNumOperands() - 1; i >= 2; i-=2) {
    MachineOperand &opVal = MPhi->getOperand(i-1);

    // Get the MachineBasicBlock equivalent of the BasicBlock that is the
    // source path the PHI.
    MachineBasicBlock &opBlock = *MPhi->getOperand(i).getMachineBasicBlock();

    MachineBasicBlock::iterator I = opBlock.getFirstTerminator();

    // Check to make sure we haven't already emitted the copy for this block.
    // This can happen because PHI nodes may have multiple entries for the
    // same basic block.  It doesn't matter which entry we use though, because
    // all incoming values are guaranteed to be the same for a particular bb.
    //
    // If we emitted a copy for this basic block already, it will be right
    // where we want to insert one now.  Just check for a definition of the
    // register we are interested in!
    //
    bool HaveNotEmitted = true;

    if (I != opBlock.begin()) {
      MachineBasicBlock::iterator PrevInst = prior(I);
      for (unsigned i = 0, e = PrevInst->getNumOperands(); i != e; ++i) {
        MachineOperand &MO = PrevInst->getOperand(i);
        if (MO.isRegister() && MO.getReg() == IncomingReg)
          if (MO.isDef()) {
            HaveNotEmitted = false;
            break;
          }
      }
    }

    if (HaveNotEmitted) { // If the copy has not already been emitted, do it.
      assert(MRegisterInfo::isVirtualRegister(opVal.getReg()) &&
             "Machine PHI Operands must all be virtual registers!");
      unsigned SrcReg = opVal.getReg();
      RegInfo->copyRegToReg(opBlock, I, IncomingReg, SrcReg, RC);

      // Now update live variable information if we have it.
      if (LV) {
        // We want to be able to insert a kill of the register if this PHI
        // (aka, the copy we just inserted) is the last use of the source
        // value.  Live variable analysis conservatively handles this by
        // saying that the value is live until the end of the block the PHI
        // entry lives in.  If the value really is dead at the PHI copy, there
        // will be no successor blocks which have the value live-in.
        //
        // Check to see if the copy is the last use, and if so, update the
        // live variables information so that it knows the copy source
        // instruction kills the incoming value.
        //
        LiveVariables::VarInfo &InRegVI = LV->getVarInfo(SrcReg);

        // Loop over all of the successors of the basic block, checking to see
        // if the value is either live in the block, or if it is killed in the
        // block.  Also check to see if this register is in use by another PHI
        // node which has not yet been eliminated.  If so, it will be killed
        // at an appropriate point later.
        //
        bool ValueIsLive = false;
        for (MachineBasicBlock::succ_iterator SI = opBlock.succ_begin(),
               E = opBlock.succ_end(); SI != E && !ValueIsLive; ++SI) {
          MachineBasicBlock *SuccMBB = *SI;

          // Is it alive in this successor?
          unsigned SuccIdx = SuccMBB->getNumber();
          if (SuccIdx < InRegVI.AliveBlocks.size() &&
              InRegVI.AliveBlocks[SuccIdx]) {
            ValueIsLive = true;
            break;
          }

          // Is it killed in this successor?
          for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i)
            if (InRegVI.Kills[i]->getParent() == SuccMBB) {
              ValueIsLive = true;
              break;
            }

          // Is it used by any PHI instructions in this block?
          if (!ValueIsLive)
            ValueIsLive = VRegPHIUseCount[SrcReg] != 0;
        }

        // Okay, if we now know that the value is not live out of the block,
        // we can add a kill marker to the copy we inserted saying that it
        // kills the incoming value!
        //
        if (!ValueIsLive) {
          MachineBasicBlock::iterator Prev = prior(I);
          LV->addVirtualRegisterKilled(SrcReg, Prev);

          // This vreg no longer lives all of the way through opBlock.
          unsigned opBlockNum = opBlock.getNumber();
          if (opBlockNum < InRegVI.AliveBlocks.size())
            InRegVI.AliveBlocks[opBlockNum] = false;
        }
      }
    }
  }

  // Really delete the PHI instruction now!
  delete MPhi;
}
<commit_msg>clean up this code a bit, no functionality change<commit_after>//===-- PhiElimination.cpp - Eliminate PHI nodes by inserting copies ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass eliminates machine instruction PHI nodes by inserting copy
// instructions.  This destroys SSA information, but is the desired input for
// some register allocators.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#include <set>
#include <algorithm>
using namespace llvm;

namespace {
  Statistic<> NumAtomic("phielim", "Number of atomic phis lowered");
  Statistic<> NumSimple("phielim", "Number of simple phis lowered");

  struct PNE : public MachineFunctionPass {
    bool runOnMachineFunction(MachineFunction &Fn) {
      bool Changed = false;

      // Eliminate PHI instructions by inserting copies into predecessor blocks.
      for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
        Changed |= EliminatePHINodes(Fn, *I);

      return Changed;
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<LiveVariables>();
      MachineFunctionPass::getAnalysisUsage(AU);
    }

  private:
    /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions
    /// in predecessor basic blocks.
    ///
    bool EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB);
    void LowerAtomicPHINode(MachineBasicBlock &MBB,
                            MachineBasicBlock::iterator AfterPHIsIt,
                            DenseMap<unsigned, VirtReg2IndexFunctor> &VUC);
  };

  RegisterPass<PNE> X("phi-node-elimination",
                      "Eliminate PHI nodes for register allocation");
}

const PassInfo *llvm::PHIEliminationID = X.getPassInfo();

/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
/// predecessor basic blocks.
///
bool PNE::EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB) {
  if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI)
    return false;   // Quick exit for basic blocks without PHIs.

  // VRegPHIUseCount - Keep track of the number of times each virtual register
  // is used by PHI nodes in successors of this block.
  DenseMap<unsigned, VirtReg2IndexFunctor> VRegPHIUseCount;
  VRegPHIUseCount.grow(MF.getSSARegMap()->getLastVirtReg());

  for (MachineBasicBlock::pred_iterator PI = MBB.pred_begin(),
         E = MBB.pred_end(); PI != E; ++PI)
    for (MachineBasicBlock::succ_iterator SI = (*PI)->succ_begin(),
           E = (*PI)->succ_end(); SI != E; ++SI)
      for (MachineBasicBlock::iterator BBI = (*SI)->begin(), E = (*SI)->end();
           BBI != E && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI)
        for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2)
          VRegPHIUseCount[BBI->getOperand(i).getReg()]++;

  // Get an iterator to the first instruction after the last PHI node (this may
  // also be the end of the basic block).
  MachineBasicBlock::iterator AfterPHIsIt = MBB.begin();
  while (AfterPHIsIt != MBB.end() &&
         AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI)
    ++AfterPHIsIt;    // Skip over all of the PHI nodes...

  while (MBB.front().getOpcode() == TargetInstrInfo::PHI) {
    LowerAtomicPHINode(MBB, AfterPHIsIt, VRegPHIUseCount);
  }
  return true;
}

/// LowerAtomicPHINode - Lower the PHI node at the top of the specified block,
/// under the assuption that it needs to be lowered in a way that supports
/// atomic execution of PHIs.  This lowering method is always correct all of the
/// time.
void PNE::LowerAtomicPHINode(MachineBasicBlock &MBB,
                             MachineBasicBlock::iterator AfterPHIsIt,
                   DenseMap<unsigned, VirtReg2IndexFunctor> &VRegPHIUseCount) {
  // Unlink the PHI node from the basic block, but don't delete the PHI yet.
  MachineInstr *MPhi = MBB.remove(MBB.begin());

  unsigned DestReg = MPhi->getOperand(0).getReg();

  // Create a new register for the incoming PHI arguments/
  MachineFunction &MF = *MBB.getParent();
  const TargetRegisterClass *RC = MF.getSSARegMap()->getRegClass(DestReg);
  unsigned IncomingReg = MF.getSSARegMap()->createVirtualRegister(RC);

  // Insert a register to register copy in the top of the current block (but
  // after any remaining phi nodes) which copies the new incoming register
  // into the phi node destination.
  //
  const MRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
  RegInfo->copyRegToReg(MBB, AfterPHIsIt, DestReg, IncomingReg, RC);

  // Update live variable information if there is any...
  LiveVariables *LV = getAnalysisToUpdate<LiveVariables>();
  if (LV) {
    MachineInstr *PHICopy = prior(AfterPHIsIt);

    // Add information to LiveVariables to know that the incoming value is
    // killed.  Note that because the value is defined in several places (once
    // each for each incoming block), the "def" block and instruction fields
    // for the VarInfo is not filled in.
    //
    LV->addVirtualRegisterKilled(IncomingReg, PHICopy);

    // Since we are going to be deleting the PHI node, if it is the last use
    // of any registers, or if the value itself is dead, we need to move this
    // information over to the new copy we just inserted.
    //
    LV->removeVirtualRegistersKilled(MPhi);

    // If the result is dead, update LV.
    if (LV->RegisterDefIsDead(MPhi, DestReg)) {
      LV->addVirtualRegisterDead(DestReg, PHICopy);
      LV->removeVirtualRegistersDead(MPhi);
    }
  }

  // Adjust the VRegPHIUseCount map to account for the removal of this PHI
  // node.
  unsigned NumPreds = (MPhi->getNumOperands()-1)/2;
  for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2)
    VRegPHIUseCount[MPhi->getOperand(i).getReg()] -= NumPreds;

  // Now loop over all of the incoming arguments, changing them to copy into
  // the IncomingReg register in the corresponding predecessor basic block.
  //
  std::set<MachineBasicBlock*> MBBsInsertedInto;
  for (int i = MPhi->getNumOperands() - 1; i >= 2; i-=2) {
    unsigned SrcReg = MPhi->getOperand(i-1).getReg();
    assert(MRegisterInfo::isVirtualRegister(SrcReg) &&
           "Machine PHI Operands must all be virtual registers!");

    // Get the MachineBasicBlock equivalent of the BasicBlock that is the
    // source path the PHI.
    MachineBasicBlock &opBlock = *MPhi->getOperand(i).getMachineBasicBlock();

    // Check to make sure we haven't already emitted the copy for this block.
    // This can happen because PHI nodes may have multiple entries for the
    // same basic block.
    if (!MBBsInsertedInto.insert(&opBlock).second)
      continue;  // If the copy has already been emitted, we're done.

    // Get an iterator pointing to the first terminator in the block (or end()).
    // This is the point where we can insert a copy if we'd like to.
    MachineBasicBlock::iterator I = opBlock.getFirstTerminator();

    // Insert the copy.
    RegInfo->copyRegToReg(opBlock, I, IncomingReg, SrcReg, RC);

    // Now update live variable information if we have it.  Otherwise we're done
    if (!LV) continue;

    // We want to be able to insert a kill of the register if this PHI
    // (aka, the copy we just inserted) is the last use of the source
    // value.  Live variable analysis conservatively handles this by
    // saying that the value is live until the end of the block the PHI
    // entry lives in.  If the value really is dead at the PHI copy, there
    // will be no successor blocks which have the value live-in.
    //
    // Check to see if the copy is the last use, and if so, update the
    // live variables information so that it knows the copy source
    // instruction kills the incoming value.
    //
    LiveVariables::VarInfo &InRegVI = LV->getVarInfo(SrcReg);

    // Loop over all of the successors of the basic block, checking to see
    // if the value is either live in the block, or if it is killed in the
    // block.  Also check to see if this register is in use by another PHI
    // node which has not yet been eliminated.  If so, it will be killed
    // at an appropriate point later.
    //

    // Is it used by any PHI instructions in this block?
    bool ValueIsLive = VRegPHIUseCount[SrcReg] != 0;

    std::vector<MachineBasicBlock*> OpSuccBlocks;

    // Otherwise, scan successors, including the BB the PHI node lives in.
    for (MachineBasicBlock::succ_iterator SI = opBlock.succ_begin(),
           E = opBlock.succ_end(); SI != E && !ValueIsLive; ++SI) {
      MachineBasicBlock *SuccMBB = *SI;

      // Is it alive in this successor?
      unsigned SuccIdx = SuccMBB->getNumber();
      if (SuccIdx < InRegVI.AliveBlocks.size() &&
          InRegVI.AliveBlocks[SuccIdx]) {
        ValueIsLive = true;
        break;
      }

      OpSuccBlocks.push_back(SuccMBB);
    }

    // Check to see if this value is live because there is a use in a successor
    // that kills it.
    if (!ValueIsLive) {
      switch (OpSuccBlocks.size()) {
      case 1: {
        MachineBasicBlock *MBB = OpSuccBlocks[0];
        for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i)
          if (InRegVI.Kills[i]->getParent() == MBB) {
            ValueIsLive = true;
            break;
          }
        break;
      }
      case 2: {
        MachineBasicBlock *MBB1 = OpSuccBlocks[0], *MBB2 = OpSuccBlocks[1];
        for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i)
          if (InRegVI.Kills[i]->getParent() == MBB1 ||
              InRegVI.Kills[i]->getParent() == MBB2) {
            ValueIsLive = true;
            break;
          }
        break;
      }
      default:
        std::sort(OpSuccBlocks.begin(), OpSuccBlocks.end());
        for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i)
          if (std::binary_search(OpSuccBlocks.begin(), OpSuccBlocks.end(),
                                 InRegVI.Kills[i]->getParent())) {
            ValueIsLive = true;
            break;
          }
      }
    }

    // Okay, if we now know that the value is not live out of the block,
    // we can add a kill marker to the copy we inserted saying that it
    // kills the incoming value!
    //
    if (!ValueIsLive) {
      MachineBasicBlock::iterator Prev = prior(I);
      LV->addVirtualRegisterKilled(SrcReg, Prev);

      // This vreg no longer lives all of the way through opBlock.
      unsigned opBlockNum = opBlock.getNumber();
      if (opBlockNum < InRegVI.AliveBlocks.size())
        InRegVI.AliveBlocks[opBlockNum] = false;
    }
  }

  // Really delete the PHI instruction now!
  delete MPhi;
  ++NumAtomic;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkExceptionObject.h"

#include "otbTerraSarCalibrationImageFilter.h"
#include "otbImage.h"
#include "otbVectorImage.h"
#include "itkExtractImageFilter.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

int otbTerraSarCalibrationImageComplexFilterTest(int argc, char * argv[])
{
  const char * inputFileName  = argv[1];
  const char * outputFileName = argv[2];
  const bool   useFastCalibration = atoi(argv[3]);
  const bool   resultsInDbs = atoi(argv[4]);

  typedef std::complex<double>                                      ComplexType;
  typedef otb::Image<ComplexType, 2>                                ImageType;
  typedef otb::ImageFileReader<ImageType>                           ReaderType;
  typedef otb::ImageFileWriter<ImageType>                           WriterType;
  typedef otb::TerraSarCalibrationImageFilter<ImageType, ImageType> FilterType;
  typedef itk::ExtractImageFilter<ImageType, ImageType>             ExtractorType;

  ReaderType::Pointer    reader = ReaderType::New();
  WriterType::Pointer    writer = WriterType::New();
  FilterType::Pointer    filter = FilterType::New();
  ExtractorType::Pointer extractor = ExtractorType::New();

  reader->SetFileName(inputFileName);
  writer->SetFileName(outputFileName);

  reader->UpdateOutputInformation();

  filter->SetInput(reader->GetOutput());
  filter->SetUseFastCalibration(useFastCalibration);
  filter->SetResultsInDecibels(resultsInDbs);

  if (argc == 9)
    {
    ImageType::RegionType region;
    ImageType::IndexType  id;
    id[0] = atoi(argv[5]);
    id[1] = atoi(argv[6]);
    ImageType::SizeType size;
    size[0] = atoi(argv[7]);
    size[1] = atoi(argv[8]);
    region.SetIndex(id);
    region.SetSize(size);
    extractor->SetExtractionRegion(region);
    extractor->SetInput(filter->GetOutput());
    writer->SetInput(extractor->GetOutput());
    }
  else
    {
    writer->SetInput(filter->GetOutput());
    }

  writer->Update();

  return EXIT_SUCCESS;
}
<commit_msg>Coorect test TorontoDb : write vectorimage<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkExceptionObject.h"

#include "otbTerraSarCalibrationImageFilter.h"
#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbVectorImage.h"
#include "itkExtractImageFilter.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkComplexToRealImageFilter.h"
#include "itkComplexToImaginaryImageFilter.h"
#include "otbImageList.h"
#include "otbImageListToVectorImageFilter.h"

int otbTerraSarCalibrationImageComplexFilterTest(int argc, char * argv[])
{
  const char * inputFileName  = argv[1];
  const char * outputFileName = argv[2];
  const bool   useFastCalibration = atoi(argv[3]);
  const bool   resultsInDbs = atoi(argv[4]);

  typedef std::complex<double>            ComplexType;
  typedef otb::Image<ComplexType, 2>      ImageCplxType;
  typedef otb::Image<double, 2>              ImageScalarType;
  typedef otb::VectorImage<double, 2>        OutputImageType;
  typedef otb::ImageList<ImageScalarType> ImageListType;

  typedef otb::ImageFileReader<ImageCplxType>                               ReaderType;
  typedef otb::ImageFileWriter<OutputImageType>                             WriterType;
  typedef otb::TerraSarCalibrationImageFilter<ImageCplxType, ImageCplxType> FilterType;
  typedef itk::ExtractImageFilter<ImageCplxType, ImageCplxType>             ExtractorType;

  typedef itk::ComplexToRealImageFilter<ImageCplxType, ImageScalarType>      RealExtractorType;
  typedef itk::ComplexToImaginaryImageFilter<ImageCplxType, ImageScalarType> ImaginaryExtractorType;
  typedef otb::ImageListToVectorImageFilter<ImageListType, OutputImageType>  ListToVectorImageFilterType;

  ReaderType::Pointer    reader = ReaderType::New();
  WriterType::Pointer    writer = WriterType::New();
  FilterType::Pointer    filter = FilterType::New();
  ExtractorType::Pointer extractor = ExtractorType::New();

  reader->SetFileName(inputFileName);
  writer->SetFileName(outputFileName);

  reader->UpdateOutputInformation();

  filter->SetInput(reader->GetOutput());
  filter->SetUseFastCalibration(useFastCalibration);
  filter->SetResultsInDecibels(resultsInDbs);

  // The rest of the code is here to translate the image complexe into
  // a VectorImage of int which each channel is the real and imagynary part
  RealExtractorType::Pointer realExt = RealExtractorType::New();
  ImaginaryExtractorType::Pointer imgExt = ImaginaryExtractorType::New();

  if (argc == 9)
    {
    ImageCplxType::RegionType region;
    ImageCplxType::IndexType  id;
    id[0] = atoi(argv[5]);
    id[1] = atoi(argv[6]);
    ImageCplxType::SizeType size;
    size[0] = atoi(argv[7]);
    size[1] = atoi(argv[8]);
    region.SetIndex(id);
    region.SetSize(size);
    extractor->SetExtractionRegion(region);
    extractor->SetInput(filter->GetOutput());

    realExt->SetInput(extractor->GetOutput());
    imgExt->SetInput(extractor->GetOutput());
    }
  else
    {
      realExt->SetInput(filter->GetOutput());
      imgExt->SetInput(filter->GetOutput());
    }

  ImageListType::Pointer imList = ImageListType::New();
  imList->PushBack(realExt->GetOutput());
  imList->PushBack(imgExt->GetOutput());
  ListToVectorImageFilterType::Pointer listCaster = ListToVectorImageFilterType::New();
  listCaster->SetInput(imList);

  writer->SetInput(listCaster->GetOutput());
  writer->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>//===--- REPLCodeCompletion.cpp - Code completion for REPL ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 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 module provides completions to the immediate mode environment.
//
//===----------------------------------------------------------------------===//

#include "swift/IDE/REPLCodeCompletion.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Module.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/DelayedParsingCallbacks.h"
#include "swift/Parse/Parser.h"
#include "swift/IDE/CodeCompletion.h"
#include "swift/Subsystems.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/MemoryBuffer.h"
#include <algorithm>

using namespace swift;
using namespace ide;

std::string toInsertableString(CodeCompletionResult *Result) {
  std::string Str;
  for (auto C : Result->getCompletionString()->getChunks()) {
    switch (C.getKind()) {
    case CodeCompletionString::Chunk::ChunkKind::Text:
    case CodeCompletionString::Chunk::ChunkKind::LeftParen:
    case CodeCompletionString::Chunk::ChunkKind::RightParen:
    case CodeCompletionString::Chunk::ChunkKind::LeftBracket:
    case CodeCompletionString::Chunk::ChunkKind::RightBracket:
    case CodeCompletionString::Chunk::ChunkKind::LeftAngle:
    case CodeCompletionString::Chunk::ChunkKind::RightAngle:
    case CodeCompletionString::Chunk::ChunkKind::Dot:
    case CodeCompletionString::Chunk::ChunkKind::Comma:
    case CodeCompletionString::Chunk::ChunkKind::ExclamationMark:
    case CodeCompletionString::Chunk::ChunkKind::QuestionMark:
    case CodeCompletionString::Chunk::ChunkKind::Ampersand:
    case CodeCompletionString::Chunk::ChunkKind::DynamicLookupMethodCallTail:
      Str += C.getText();
      break;

    case CodeCompletionString::Chunk::ChunkKind::CallParameterName:
    case CodeCompletionString::Chunk::ChunkKind::CallParameterColon:
    case CodeCompletionString::Chunk::ChunkKind::CallParameterType:
    case CodeCompletionString::Chunk::ChunkKind::OptionalBegin:
    case CodeCompletionString::Chunk::ChunkKind::CallParameterBegin:
    case CodeCompletionString::Chunk::ChunkKind::GenericParameterBegin:
    case CodeCompletionString::Chunk::ChunkKind::GenericParameterName:
    case CodeCompletionString::Chunk::ChunkKind::TypeAnnotation:
      return Str;
    }
  }
  return Str;
}

namespace swift {
class REPLCodeCompletionConsumer : public CodeCompletionConsumer {
  REPLCompletions &Completions;

public:
  REPLCodeCompletionConsumer(REPLCompletions &Completions)
      : Completions(Completions) {}

  void handleResults(MutableArrayRef<CodeCompletionResult *> Results) override {
    CodeCompletionContext::sortCompletionResults(Results);
    for (auto Result : Results) {
      std::string InsertableString = toInsertableString(Result);
      if (StringRef(InsertableString).startswith(Completions.Prefix)) {
        llvm::SmallString<128> PrintedResult;
        {
          llvm::raw_svector_ostream OS(PrintedResult);
          Result->print(OS);
        }
        Completions.CompletionStrings.push_back(
            Completions.CompletionContext.copyString(PrintedResult));

        InsertableString = InsertableString.substr(Completions.Prefix.size());

        Completions.CookedResults.push_back(
            { Completions.CompletionContext.copyString(InsertableString),
              Result->getNumBytesToErase() });
      }
    }
  }
};
} // namespace swift

REPLCompletions::REPLCompletions()
    : State(CompletionState::Invalid), CompletionContext(CompletionCache) {
  // Create a CodeCompletionConsumer.
  Consumer.reset(new REPLCodeCompletionConsumer(*this));

  // Cerate a factory for code completion callbacks that will feed the
  // Consumer.
  CompletionCallbacksFactory.reset(
      ide::makeCodeCompletionCallbacksFactory(CompletionContext,
                                              *Consumer.get()));
}

static void
doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID,
                 CodeCompletionCallbacksFactory *CompletionCallbacksFactory) {
  // Temporarily disable printing the diagnostics.
  ASTContext &Ctx = SF.getASTContext();
  auto DiagnosticConsumers = Ctx.Diags.takeConsumers();

  std::string AugmentedCode = EnteredCode.str();
  AugmentedCode += '\0';
  *BufferID = Ctx.SourceMgr.addMemBufferCopy(AugmentedCode, "<REPL Input>");

  const unsigned CodeCompletionOffset = AugmentedCode.size() - 1;

  Ctx.SourceMgr.setCodeCompletionPoint(*BufferID, CodeCompletionOffset);

  // Parse, typecheck and temporarily insert the incomplete code into the AST.
  const unsigned OriginalDeclCount = SF.Decls.size();

  unsigned CurElem = OriginalDeclCount;
  PersistentParserState PersistentState;
  std::unique_ptr<DelayedParsingCallbacks> DelayedCB(
      new CodeCompleteDelayedCallbacks(Ctx.SourceMgr.getCodeCompletionLoc()));
  bool Done;
  do {
    parseIntoSourceFile(SF, *BufferID, &Done, nullptr, &PersistentState,
                        DelayedCB.get());
    performTypeChecking(SF, PersistentState.getTopLevelContext(), CurElem);
    CurElem = SF.Decls.size();
  } while (!Done);

  performDelayedParsing(&SF, PersistentState, CompletionCallbacksFactory);

  // Now we are done with code completion.  Remove the declarations we
  // temporarily inserted.
  SF.Decls.resize(OriginalDeclCount);

  // Add the diagnostic consumers back.
  for (auto DC : DiagnosticConsumers)
    Ctx.Diags.addConsumer(*DC);

  Ctx.Diags.resetHadAnyError();
}

void REPLCompletions::populate(SourceFile &SF, StringRef EnteredCode) {
  Prefix = "";
  Root.reset();
  CurrentCompletionIdx = ~size_t(0);

  CompletionStrings.clear();
  CookedResults.clear();

  assert(SF.Kind == SourceFileKind::REPL && "Can't append to a non-REPL file");

  unsigned BufferID;
  doCodeCompletion(SF, EnteredCode, &BufferID,
                   CompletionCallbacksFactory.get());

  ASTContext &Ctx = SF.getASTContext();
  std::vector<Token> Tokens = tokenize(Ctx.LangOpts, Ctx.SourceMgr, BufferID);

  if (!Tokens.empty() && Tokens.back().is(tok::code_complete))
    Tokens.pop_back();

  if (!Tokens.empty()) {
    Token &LastToken = Tokens.back();
    if (LastToken.is(tok::identifier) || LastToken.isKeyword()) {
      Prefix = LastToken.getText();

      unsigned Offset = Ctx.SourceMgr.getLocOffsetInBuffer(LastToken.getLoc(),
                                                           BufferID);

      doCodeCompletion(SF, EnteredCode.substr(0, Offset),
                       &BufferID, CompletionCallbacksFactory.get());
    }
  }

  if (CookedResults.empty())
    State = CompletionState::Empty;
  else if (CookedResults.size() == 1)
    State = CompletionState::Unique;
  else
    State = CompletionState::CompletedRoot;
}

StringRef REPLCompletions::getRoot() const {
  if (Root)
    return Root.getValue();

  if (CookedResults.empty()) {
    Root = std::string();
    return Root.getValue();
  }

  std::string RootStr = CookedResults[0].InsertableString;
  for (auto R : CookedResults) {
    if (R.NumBytesToErase != 0) {
      RootStr.resize(0);
      break;
    }
    auto MismatchPlace = std::mismatch(RootStr.begin(), RootStr.end(),
                                       R.InsertableString.begin());
    RootStr.resize(MismatchPlace.first - RootStr.begin());
  }
  Root = RootStr;
  return Root.getValue();
}

REPLCompletions::CookedResult REPLCompletions::getPreviousStem() const {
  if (CurrentCompletionIdx == ~size_t(0) || CookedResults.empty())
    return {};

  const auto &Result = CookedResults[CurrentCompletionIdx];
  return { Result.InsertableString.substr(getRoot().size()),
           Result.NumBytesToErase };
}

REPLCompletions::CookedResult REPLCompletions::getNextStem() {
  if (CookedResults.empty())
    return {};

  CurrentCompletionIdx++;
  if (CurrentCompletionIdx >= CookedResults.size())
    CurrentCompletionIdx = 0;

  const auto &Result = CookedResults[CurrentCompletionIdx];
  return { Result.InsertableString.substr(getRoot().size()),
           Result.NumBytesToErase };
}

void REPLCompletions::reset() { State = CompletionState::Invalid; }

<commit_msg>REPL code completion: handle PreferredCursorPosition chunk<commit_after>//===--- REPLCodeCompletion.cpp - Code completion for REPL ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 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 module provides completions to the immediate mode environment.
//
//===----------------------------------------------------------------------===//

#include "swift/IDE/REPLCodeCompletion.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Module.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/DelayedParsingCallbacks.h"
#include "swift/Parse/Parser.h"
#include "swift/IDE/CodeCompletion.h"
#include "swift/Subsystems.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/MemoryBuffer.h"
#include <algorithm>

using namespace swift;
using namespace ide;

std::string toInsertableString(CodeCompletionResult *Result) {
  std::string Str;
  for (auto C : Result->getCompletionString()->getChunks()) {
    switch (C.getKind()) {
    case CodeCompletionString::Chunk::ChunkKind::Text:
    case CodeCompletionString::Chunk::ChunkKind::LeftParen:
    case CodeCompletionString::Chunk::ChunkKind::RightParen:
    case CodeCompletionString::Chunk::ChunkKind::LeftBracket:
    case CodeCompletionString::Chunk::ChunkKind::RightBracket:
    case CodeCompletionString::Chunk::ChunkKind::LeftAngle:
    case CodeCompletionString::Chunk::ChunkKind::RightAngle:
    case CodeCompletionString::Chunk::ChunkKind::Dot:
    case CodeCompletionString::Chunk::ChunkKind::Comma:
    case CodeCompletionString::Chunk::ChunkKind::ExclamationMark:
    case CodeCompletionString::Chunk::ChunkKind::QuestionMark:
    case CodeCompletionString::Chunk::ChunkKind::Ampersand:
    case CodeCompletionString::Chunk::ChunkKind::DynamicLookupMethodCallTail:
      Str += C.getText();
      break;

    case CodeCompletionString::Chunk::ChunkKind::CallParameterName:
    case CodeCompletionString::Chunk::ChunkKind::CallParameterColon:
    case CodeCompletionString::Chunk::ChunkKind::CallParameterType:
    case CodeCompletionString::Chunk::ChunkKind::OptionalBegin:
    case CodeCompletionString::Chunk::ChunkKind::CallParameterBegin:
    case CodeCompletionString::Chunk::ChunkKind::GenericParameterBegin:
    case CodeCompletionString::Chunk::ChunkKind::GenericParameterName:
    case CodeCompletionString::Chunk::ChunkKind::TypeAnnotation:
    case CodeCompletionString::Chunk::ChunkKind::PreferredCursorPosition:
      return Str;
    }
  }
  return Str;
}

namespace swift {
class REPLCodeCompletionConsumer : public CodeCompletionConsumer {
  REPLCompletions &Completions;

public:
  REPLCodeCompletionConsumer(REPLCompletions &Completions)
      : Completions(Completions) {}

  void handleResults(MutableArrayRef<CodeCompletionResult *> Results) override {
    CodeCompletionContext::sortCompletionResults(Results);
    for (auto Result : Results) {
      std::string InsertableString = toInsertableString(Result);
      if (StringRef(InsertableString).startswith(Completions.Prefix)) {
        llvm::SmallString<128> PrintedResult;
        {
          llvm::raw_svector_ostream OS(PrintedResult);
          Result->print(OS);
        }
        Completions.CompletionStrings.push_back(
            Completions.CompletionContext.copyString(PrintedResult));

        InsertableString = InsertableString.substr(Completions.Prefix.size());

        Completions.CookedResults.push_back(
            { Completions.CompletionContext.copyString(InsertableString),
              Result->getNumBytesToErase() });
      }
    }
  }
};
} // namespace swift

REPLCompletions::REPLCompletions()
    : State(CompletionState::Invalid), CompletionContext(CompletionCache) {
  // Create a CodeCompletionConsumer.
  Consumer.reset(new REPLCodeCompletionConsumer(*this));

  // Cerate a factory for code completion callbacks that will feed the
  // Consumer.
  CompletionCallbacksFactory.reset(
      ide::makeCodeCompletionCallbacksFactory(CompletionContext,
                                              *Consumer.get()));
}

static void
doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID,
                 CodeCompletionCallbacksFactory *CompletionCallbacksFactory) {
  // Temporarily disable printing the diagnostics.
  ASTContext &Ctx = SF.getASTContext();
  auto DiagnosticConsumers = Ctx.Diags.takeConsumers();

  std::string AugmentedCode = EnteredCode.str();
  AugmentedCode += '\0';
  *BufferID = Ctx.SourceMgr.addMemBufferCopy(AugmentedCode, "<REPL Input>");

  const unsigned CodeCompletionOffset = AugmentedCode.size() - 1;

  Ctx.SourceMgr.setCodeCompletionPoint(*BufferID, CodeCompletionOffset);

  // Parse, typecheck and temporarily insert the incomplete code into the AST.
  const unsigned OriginalDeclCount = SF.Decls.size();

  unsigned CurElem = OriginalDeclCount;
  PersistentParserState PersistentState;
  std::unique_ptr<DelayedParsingCallbacks> DelayedCB(
      new CodeCompleteDelayedCallbacks(Ctx.SourceMgr.getCodeCompletionLoc()));
  bool Done;
  do {
    parseIntoSourceFile(SF, *BufferID, &Done, nullptr, &PersistentState,
                        DelayedCB.get());
    performTypeChecking(SF, PersistentState.getTopLevelContext(), CurElem);
    CurElem = SF.Decls.size();
  } while (!Done);

  performDelayedParsing(&SF, PersistentState, CompletionCallbacksFactory);

  // Now we are done with code completion.  Remove the declarations we
  // temporarily inserted.
  SF.Decls.resize(OriginalDeclCount);

  // Add the diagnostic consumers back.
  for (auto DC : DiagnosticConsumers)
    Ctx.Diags.addConsumer(*DC);

  Ctx.Diags.resetHadAnyError();
}

void REPLCompletions::populate(SourceFile &SF, StringRef EnteredCode) {
  Prefix = "";
  Root.reset();
  CurrentCompletionIdx = ~size_t(0);

  CompletionStrings.clear();
  CookedResults.clear();

  assert(SF.Kind == SourceFileKind::REPL && "Can't append to a non-REPL file");

  unsigned BufferID;
  doCodeCompletion(SF, EnteredCode, &BufferID,
                   CompletionCallbacksFactory.get());

  ASTContext &Ctx = SF.getASTContext();
  std::vector<Token> Tokens = tokenize(Ctx.LangOpts, Ctx.SourceMgr, BufferID);

  if (!Tokens.empty() && Tokens.back().is(tok::code_complete))
    Tokens.pop_back();

  if (!Tokens.empty()) {
    Token &LastToken = Tokens.back();
    if (LastToken.is(tok::identifier) || LastToken.isKeyword()) {
      Prefix = LastToken.getText();

      unsigned Offset = Ctx.SourceMgr.getLocOffsetInBuffer(LastToken.getLoc(),
                                                           BufferID);

      doCodeCompletion(SF, EnteredCode.substr(0, Offset),
                       &BufferID, CompletionCallbacksFactory.get());
    }
  }

  if (CookedResults.empty())
    State = CompletionState::Empty;
  else if (CookedResults.size() == 1)
    State = CompletionState::Unique;
  else
    State = CompletionState::CompletedRoot;
}

StringRef REPLCompletions::getRoot() const {
  if (Root)
    return Root.getValue();

  if (CookedResults.empty()) {
    Root = std::string();
    return Root.getValue();
  }

  std::string RootStr = CookedResults[0].InsertableString;
  for (auto R : CookedResults) {
    if (R.NumBytesToErase != 0) {
      RootStr.resize(0);
      break;
    }
    auto MismatchPlace = std::mismatch(RootStr.begin(), RootStr.end(),
                                       R.InsertableString.begin());
    RootStr.resize(MismatchPlace.first - RootStr.begin());
  }
  Root = RootStr;
  return Root.getValue();
}

REPLCompletions::CookedResult REPLCompletions::getPreviousStem() const {
  if (CurrentCompletionIdx == ~size_t(0) || CookedResults.empty())
    return {};

  const auto &Result = CookedResults[CurrentCompletionIdx];
  return { Result.InsertableString.substr(getRoot().size()),
           Result.NumBytesToErase };
}

REPLCompletions::CookedResult REPLCompletions::getNextStem() {
  if (CookedResults.empty())
    return {};

  CurrentCompletionIdx++;
  if (CurrentCompletionIdx >= CookedResults.size())
    CurrentCompletionIdx = 0;

  const auto &Result = CookedResults[CurrentCompletionIdx];
  return { Result.InsertableString.substr(getRoot().size()),
           Result.NumBytesToErase };
}

void REPLCompletions::reset() { State = CompletionState::Invalid; }

<|endoftext|>


<commit_before>/* /////////////////////////////////////////////////////////////////////////
 * File:        example.cpp.main.1.cpp
 *
 * Purpose:     Implementation file for the example.cpp.main.1 library.
 *
 * Created:     5th January 2011
 * Updated:     9th February 2021
 *
 * Status:      Wizard-generated
 *
 * License:     (Licensed under the Synesis Software Open License)
 *
 *              Copyright (c) 2011-2021, Synesis Software Pty Ltd.
 *              All rights reserved.
 *
 *              www:        http://www.synesis.com.au/software
 *
 * ////////////////////////////////////////////////////////////////////// */

/* /////////////////////////////////////////////////////////////////////////
 * feature control
 */

// This is defined for illustrative purposes. You are advised to *not*
// define this in production code. See Quality Matters, #5: "Exceptions:
// The Worst Form of Error Handling, Apart From All The Others" for details
// (http://quality-matters-to.us/).
#define PANTHEIOS_EXTRAS_MAIN_USE_CATCHALL

/* /////////////////////////////////////////////////////////////////////////
 * includes
 */

/* Pantheios Extras header files */
#include <pantheios/extras/main.hpp>

/* Pantheios header files */
#include <pantheios/pantheios.h>

/* STLSoft header files */
#include <stlsoft/stlsoft.h>

/* Standard C header files */
#include <stdlib.h>

/* /////////////////////////////////////////////////////////////////////////
 * globals
 */

PANTHEIOS_EXTERN_C PAN_CHAR_T const PANTHEIOS_FE_PROCESS_IDENTITY[] = PANTHEIOS_LITERAL_STRING("example.cpp.main.1");

/* ////////////////////////////////////////////////////////////////////// */

#ifndef USE_wmain

int main0(int argc, char** argv)
{
    /* do the "main" business of main() here, without worrying about
     * initialising Pantheios libraries
     */

    /* in this case, we simply throw a given type of exception, as
     * requested by the user
     */

    if (argc == 2)
    {
        if (0 == strcmp(argv[1], "memory"))
        {
            throw std::bad_alloc();
        }
        else
        if (0 == strcmp(argv[1], "root"))
        {
            throw std::runtime_error("oops!");
        }
        else
        {
            throw 1.0;
        }
    }

    printf(
        "USAGE: %s {memory|root|other}\n"
    ,   argv[0]
    );

    return EXIT_SUCCESS;
}

int main(int argc, char** argv)
{
    return pantheios::extras::main::invoke(argc, argv, main0);
}

#else // ? USE_wmain

int main0(int argc, wchar_t** argv)
{
    /* do the "main" business of main() here, without worrying about
     * initialising Pantheios libraries
     */

    /* in this case, we simply throw a given type of exception, as
     * requested by the user
     */

    if (argc == 2)
    {
        if (0 == wcscmp(argv[1], L"memory"))
        {
            throw std::bad_alloc();
        }
        else
        if (0 == wcscmp(argv[1], L"root"))
        {
            throw std::runtime_error("oops!");
        }
        else
        {
            throw 1.0;
        }
    }

    printf(
        "USAGE: %s {memory|root|other}\n"
    ,   argv[0]
    );

    return EXIT_SUCCESS;
}

int wmain(int argc, wchar_t** argv)
{
    return pantheios::extras::main::invoke(argc, argv, main0);
}

#endif // !USE_wmain

/* ///////////////////////////// end of file //////////////////////////// */

<commit_msg>~ wide-string implementation<commit_after>/* /////////////////////////////////////////////////////////////////////////
 * File:        example.cpp.main.1.cpp
 *
 * Purpose:     Implementation file for the example.cpp.main.1 library.
 *
 * Created:     5th January 2011
 * Updated:     9th February 2021
 *
 * Status:      Wizard-generated
 *
 * License:     (Licensed under the Synesis Software Open License)
 *
 *              Copyright (c) 2011-2021, Synesis Software Pty Ltd.
 *              All rights reserved.
 *
 *              www:        http://www.synesis.com.au/software
 *
 * ////////////////////////////////////////////////////////////////////// */

/* /////////////////////////////////////////////////////////////////////////
 * feature control
 */

// This is defined for illustrative purposes. You are advised to *not*
// define this in production code. See Quality Matters, #5: "Exceptions:
// The Worst Form of Error Handling, Apart From All The Others" for details
// (http://quality-matters-to.us/).
#define PANTHEIOS_EXTRAS_MAIN_USE_CATCHALL

/* /////////////////////////////////////////////////////////////////////////
 * includes
 */

/* Pantheios Extras header files */
#include <pantheios/extras/main.hpp>

/* Pantheios header files */
#include <pantheios/pantheios.h>

/* STLSoft header files */
#include <stlsoft/stlsoft.h>

/* Standard C header files */
#include <stdlib.h>

/* /////////////////////////////////////////////////////////////////////////
 * globals
 */

PANTHEIOS_EXTERN_C PAN_CHAR_T const PANTHEIOS_FE_PROCESS_IDENTITY[] = PANTHEIOS_LITERAL_STRING("example.cpp.main.1");

/* ////////////////////////////////////////////////////////////////////// */

#ifndef USE_wmain

int main0(int argc, char** argv)
{
    /* do the "main" business of main() here, without worrying about
     * initialising Pantheios libraries
     */

    /* in this case, we simply throw a given type of exception, as
     * requested by the user
     */

    if (argc == 2)
    {
        if (0 == strcmp(argv[1], "memory"))
        {
            throw std::bad_alloc();
        }
        else
        if (0 == strcmp(argv[1], "root"))
        {
            throw std::runtime_error("oops!");
        }
        else
        {
            throw 1.0;
        }
    }

    printf(
        "USAGE: %s {memory|root|other}\n"
    ,   argv[0]
    );

    return EXIT_SUCCESS;
}

int main(int argc, char** argv)
{
    return pantheios::extras::main::invoke(argc, argv, main0);
}

#else // ? USE_wmain

int main0(int argc, wchar_t** argv)
{
    /* do the "main" business of main() here, without worrying about
     * initialising Pantheios libraries
     */

    /* in this case, we simply throw a given type of exception, as
     * requested by the user
     */

    if (argc == 2)
    {
        if (0 == wcscmp(argv[1], L"memory"))
        {
            throw std::bad_alloc();
        }
        else
        if (0 == wcscmp(argv[1], L"root"))
        {
            throw std::runtime_error("oops!");
        }
        else
        {
            throw 1.0;
        }
    }

    wprintf(
        L"USAGE: %s {memory|root|other}\n"
    ,   argv[0]
    );

    return EXIT_SUCCESS;
}

int wmain(int argc, wchar_t** argv)
{
    return pantheios::extras::main::invoke(argc, argv, main0);
}

#endif // !USE_wmain

/* ///////////////////////////// end of file //////////////////////////// */

<|endoftext|>