<commit_before>//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Disassembler.h"
#include "llvm-c/Disassembler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbolizer.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/TargetRegistry.h"

using namespace llvm;

// LLVMCreateDisasm() creates a disassembler for the TripleName.  Symbolic
// disassembly is supported by passing a block of information in the DisInfo
// parameter and specifying the TagType and callback functions as described in
// the header llvm-c/Disassembler.h .  The pointer to the block and the
// functions can all be passed as NULL.  If successful, this returns a
// disassembler context.  If not, it returns NULL.
//
LLVMDisasmContextRef
LLVMCreateDisasmCPUFeatures(const char *Triple, const char *CPU,
                            const char *Features, void *DisInfo, int TagType,
                            LLVMOpInfoCallback GetOpInfo,
                            LLVMSymbolLookupCallback SymbolLookUp) {
  // Get the target.
  std::string Error;
  const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
  if (!TheTarget)
    return nullptr;

  const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple);
  if (!MRI)
    return nullptr;

  // Get the assembler info needed to setup the MCContext.
  const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(*MRI, Triple);
  if (!MAI)
    return nullptr;

  const MCInstrInfo *MII = TheTarget->createMCInstrInfo();
  if (!MII)
    return nullptr;

  const MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(Triple, CPU,
                                                                Features);
  if (!STI)
    return nullptr;

  // Set up the MCContext for creating symbols and MCExpr's.
  MCContext *Ctx = new MCContext(MAI, MRI, nullptr);
  if (!Ctx)
    return nullptr;

  // Set up disassembler.
  MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI, *Ctx);
  if (!DisAsm)
    return nullptr;

  std::unique_ptr<MCRelocationInfo> RelInfo(
      TheTarget->createMCRelocationInfo(Triple, *Ctx));
  if (!RelInfo)
    return nullptr;

  std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer(
      Triple, GetOpInfo, SymbolLookUp, DisInfo, Ctx, RelInfo.release()));
  DisAsm->setSymbolizer(std::move(Symbolizer));

  // Set up the instruction printer.
  int AsmPrinterVariant = MAI->getAssemblerDialect();
  MCInstPrinter *IP = TheTarget->createMCInstPrinter(AsmPrinterVariant,
                                                     *MAI, *MII, *MRI, *STI);
  if (!IP)
    return nullptr;

  LLVMDisasmContext *DC = new LLVMDisasmContext(Triple, DisInfo, TagType,
                                                GetOpInfo, SymbolLookUp,
                                                TheTarget, MAI, MRI,
                                                STI, MII, Ctx, DisAsm, IP);
  if (!DC)
    return nullptr;

  DC->setCPU(CPU);
  return DC;
}

LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU,
                                         void *DisInfo, int TagType,
                                         LLVMOpInfoCallback GetOpInfo,
                                         LLVMSymbolLookupCallback SymbolLookUp){
  return LLVMCreateDisasmCPUFeatures(Triple, CPU, "", DisInfo, TagType,
                                     GetOpInfo, SymbolLookUp);
}

LLVMDisasmContextRef LLVMCreateDisasm(const char *Triple, void *DisInfo,
                                      int TagType, LLVMOpInfoCallback GetOpInfo,
                                      LLVMSymbolLookupCallback SymbolLookUp) {
  return LLVMCreateDisasmCPUFeatures(Triple, "", "", DisInfo, TagType,
                                     GetOpInfo, SymbolLookUp);
}

//
// LLVMDisasmDispose() disposes of the disassembler specified by the context.
//
void LLVMDisasmDispose(LLVMDisasmContextRef DCR){
  LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
  delete DC;
}

namespace {
//
// The memory object created by LLVMDisasmInstruction().
//
class DisasmMemoryObject : public MemoryObject {
  uint8_t *Bytes;
  uint64_t Size;
  uint64_t BasePC;
public:
  DisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) :
                     Bytes(bytes), Size(size), BasePC(basePC) {}

  uint64_t getBase() const override { return BasePC; }
  uint64_t getExtent() const override { return Size; }

  int readByte(uint64_t Addr, uint8_t *Byte) const override {
    if (Addr - BasePC >= Size)
      return -1;
    *Byte = Bytes[Addr - BasePC];
    return 0;
  }
};
} // end anonymous namespace

/// \brief Emits the comments that are stored in \p DC comment stream.
/// Each comment in the comment stream must end with a newline.
static void emitComments(LLVMDisasmContext *DC,
                         formatted_raw_ostream &FormattedOS) {
  // Flush the stream before taking its content.
  DC->CommentStream.flush();
  StringRef Comments = DC->CommentsToEmit.str();
  // Get the default information for printing a comment.
  const MCAsmInfo *MAI = DC->getAsmInfo();
  const char *CommentBegin = MAI->getCommentString();
  unsigned CommentColumn = MAI->getCommentColumn();
  bool IsFirst = true;
  while (!Comments.empty()) {
    if (!IsFirst)
      FormattedOS << '\n';
    // Emit a line of comments.
    FormattedOS.PadToColumn(CommentColumn);
    size_t Position = Comments.find('\n');
    FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
    // Move after the newline character.
    Comments = Comments.substr(Position+1);
    IsFirst = false;
  }
  FormattedOS.flush();

  // Tell the comment stream that the vector changed underneath it.
  DC->CommentsToEmit.clear();
  DC->CommentStream.resync();
}

/// \brief Gets latency information for \p Inst form the itinerary
/// scheduling model, based on \p DC information.
/// \return The maximum expected latency over all the operands or -1
/// if no information are available.
static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
  const int NoInformationAvailable = -1;

  // Check if we have a CPU to get the itinerary information.
  if (DC->getCPU().empty())
    return NoInformationAvailable;

  // Get itinerary information.
  const MCSubtargetInfo *STI = DC->getSubtargetInfo();
  InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU());
  // Get the scheduling class of the requested instruction.
  const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
  unsigned SCClass = Desc.getSchedClass();

  int Latency = 0;
  for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd;
       ++OpIdx)
    Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx));

  return Latency;
}

/// \brief Gets latency information for \p Inst, based on \p DC information.
/// \return The maximum expected latency over all the definitions or -1
/// if no information are available.
static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
  // Try to compute scheduling information.
  const MCSubtargetInfo *STI = DC->getSubtargetInfo();
  const MCSchedModel SCModel = STI->getSchedModel();
  const int NoInformationAvailable = -1;

  // Check if we have a scheduling model for instructions.
  if (!SCModel.hasInstrSchedModel())
    // Try to fall back to the itinerary model if the scheduling model doesn't
    // have a scheduling table.  Note the default does not have a table.
    return getItineraryLatency(DC, Inst);

  // Get the scheduling class of the requested instruction.
  const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
  unsigned SCClass = Desc.getSchedClass();
  const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass);
  // Resolving the variant SchedClass requires an MI to pass to
  // SubTargetInfo::resolveSchedClass.
  if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
    return NoInformationAvailable;

  // Compute output latency.
  int Latency = 0;
  for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
       DefIdx != DefEnd; ++DefIdx) {
    // Lookup the definition's write latency in SubtargetInfo.
    const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc,
                                                                   DefIdx);
    Latency = std::max(Latency, WLEntry->Cycles);
  }

  return Latency;
}

/// \brief Emits latency information in DC->CommentStream for \p Inst, based
/// on the information available in \p DC.
static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
  int Latency = getLatency(DC, Inst);

  // Report only interesting latency.
  if (Latency < 2)
    return;

  DC->CommentStream << "Latency: " << Latency << '\n';
}

//
// LLVMDisasmInstruction() disassembles a single instruction using the
// disassembler context specified in the parameter DC.  The bytes of the
// instruction are specified in the parameter Bytes, and contains at least
// BytesSize number of bytes.  The instruction is at the address specified by
// the PC parameter.  If a valid instruction can be disassembled its string is
// returned indirectly in OutString which whos size is specified in the
// parameter OutStringSize.  This function returns the number of bytes in the
// instruction or zero if there was no valid instruction.  If this function
// returns zero the caller will have to pick how many bytes they want to step
// over by printing a .byte, .long etc. to continue.
//
size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
                             uint64_t BytesSize, uint64_t PC, char *OutString,
                             size_t OutStringSize){
  LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
  // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject.
  DisasmMemoryObject MemoryObject(Bytes, BytesSize, PC);

  uint64_t Size;
  MCInst Inst;
  const MCDisassembler *DisAsm = DC->getDisAsm();
  MCInstPrinter *IP = DC->getIP();
  MCDisassembler::DecodeStatus S;
  SmallVector<char, 64> InsnStr;
  raw_svector_ostream Annotations(InsnStr);
  S = DisAsm->getInstruction(Inst, Size, MemoryObject, PC,
                             /*REMOVE*/ nulls(), Annotations);
  switch (S) {
  case MCDisassembler::Fail:
  case MCDisassembler::SoftFail:
    // FIXME: Do something different for soft failure modes?
    return 0;

  case MCDisassembler::Success: {
    Annotations.flush();
    StringRef AnnotationsStr = Annotations.str();

    SmallVector<char, 64> InsnStr;
    raw_svector_ostream OS(InsnStr);
    formatted_raw_ostream FormattedOS(OS);
    IP->printInst(&Inst, FormattedOS, AnnotationsStr);

    if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency)
      emitLatency(DC, Inst);

    emitComments(DC, FormattedOS);
    OS.flush();

    assert(OutStringSize != 0 && "Output buffer cannot be zero size");
    size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());
    std::memcpy(OutString, InsnStr.data(), OutputSize);
    OutString[OutputSize] = '\0'; // Terminate string.

    return Size;
  }
  }
  llvm_unreachable("Invalid DecodeStatus!");
}

//
// LLVMSetDisasmOptions() sets the disassembler's options.  It returns 1 if it
// can set all the Options and 0 otherwise.
//
int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
  if (Options & LLVMDisassembler_Option_UseMarkup){
      LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
      MCInstPrinter *IP = DC->getIP();
      IP->setUseMarkup(1);
      DC->addOptions(LLVMDisassembler_Option_UseMarkup);
      Options &= ~LLVMDisassembler_Option_UseMarkup;
  }
  if (Options & LLVMDisassembler_Option_PrintImmHex){
      LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
      MCInstPrinter *IP = DC->getIP();
      IP->setPrintImmHex(1);
      DC->addOptions(LLVMDisassembler_Option_PrintImmHex);
      Options &= ~LLVMDisassembler_Option_PrintImmHex;
  }
  if (Options & LLVMDisassembler_Option_AsmPrinterVariant){
      LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
      // Try to set up the new instruction printer.
      const MCAsmInfo *MAI = DC->getAsmInfo();
      const MCInstrInfo *MII = DC->getInstrInfo();
      const MCRegisterInfo *MRI = DC->getRegisterInfo();
      const MCSubtargetInfo *STI = DC->getSubtargetInfo();
      int AsmPrinterVariant = MAI->getAssemblerDialect();
      AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0;
      MCInstPrinter *IP = DC->getTarget()->createMCInstPrinter(
          AsmPrinterVariant, *MAI, *MII, *MRI, *STI);
      if (IP) {
        DC->setIP(IP);
        DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant);
        Options &= ~LLVMDisassembler_Option_AsmPrinterVariant;
      }
  }
  if (Options & LLVMDisassembler_Option_SetInstrComments) {
    LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
    MCInstPrinter *IP = DC->getIP();
    IP->setCommentStream(DC->CommentStream);
    DC->addOptions(LLVMDisassembler_Option_SetInstrComments);
    Options &= ~LLVMDisassembler_Option_SetInstrComments;
  }
  if (Options & LLVMDisassembler_Option_PrintLatency) {
    LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
    DC->addOptions(LLVMDisassembler_Option_PrintLatency);
    Options &= ~LLVMDisassembler_Option_PrintLatency;
  }
  return (Options == 0);
}
<commit_msg>Use a StringRefMemoryObject. NFC.<commit_after>//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Disassembler.h"
#include "llvm-c/Disassembler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbolizer.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/StringRefMemoryObject.h"
#include "llvm/Support/TargetRegistry.h"

using namespace llvm;

// LLVMCreateDisasm() creates a disassembler for the TripleName.  Symbolic
// disassembly is supported by passing a block of information in the DisInfo
// parameter and specifying the TagType and callback functions as described in
// the header llvm-c/Disassembler.h .  The pointer to the block and the
// functions can all be passed as NULL.  If successful, this returns a
// disassembler context.  If not, it returns NULL.
//
LLVMDisasmContextRef
LLVMCreateDisasmCPUFeatures(const char *Triple, const char *CPU,
                            const char *Features, void *DisInfo, int TagType,
                            LLVMOpInfoCallback GetOpInfo,
                            LLVMSymbolLookupCallback SymbolLookUp) {
  // Get the target.
  std::string Error;
  const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
  if (!TheTarget)
    return nullptr;

  const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple);
  if (!MRI)
    return nullptr;

  // Get the assembler info needed to setup the MCContext.
  const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(*MRI, Triple);
  if (!MAI)
    return nullptr;

  const MCInstrInfo *MII = TheTarget->createMCInstrInfo();
  if (!MII)
    return nullptr;

  const MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(Triple, CPU,
                                                                Features);
  if (!STI)
    return nullptr;

  // Set up the MCContext for creating symbols and MCExpr's.
  MCContext *Ctx = new MCContext(MAI, MRI, nullptr);
  if (!Ctx)
    return nullptr;

  // Set up disassembler.
  MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI, *Ctx);
  if (!DisAsm)
    return nullptr;

  std::unique_ptr<MCRelocationInfo> RelInfo(
      TheTarget->createMCRelocationInfo(Triple, *Ctx));
  if (!RelInfo)
    return nullptr;

  std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer(
      Triple, GetOpInfo, SymbolLookUp, DisInfo, Ctx, RelInfo.release()));
  DisAsm->setSymbolizer(std::move(Symbolizer));

  // Set up the instruction printer.
  int AsmPrinterVariant = MAI->getAssemblerDialect();
  MCInstPrinter *IP = TheTarget->createMCInstPrinter(AsmPrinterVariant,
                                                     *MAI, *MII, *MRI, *STI);
  if (!IP)
    return nullptr;

  LLVMDisasmContext *DC = new LLVMDisasmContext(Triple, DisInfo, TagType,
                                                GetOpInfo, SymbolLookUp,
                                                TheTarget, MAI, MRI,
                                                STI, MII, Ctx, DisAsm, IP);
  if (!DC)
    return nullptr;

  DC->setCPU(CPU);
  return DC;
}

LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU,
                                         void *DisInfo, int TagType,
                                         LLVMOpInfoCallback GetOpInfo,
                                         LLVMSymbolLookupCallback SymbolLookUp){
  return LLVMCreateDisasmCPUFeatures(Triple, CPU, "", DisInfo, TagType,
                                     GetOpInfo, SymbolLookUp);
}

LLVMDisasmContextRef LLVMCreateDisasm(const char *Triple, void *DisInfo,
                                      int TagType, LLVMOpInfoCallback GetOpInfo,
                                      LLVMSymbolLookupCallback SymbolLookUp) {
  return LLVMCreateDisasmCPUFeatures(Triple, "", "", DisInfo, TagType,
                                     GetOpInfo, SymbolLookUp);
}

//
// LLVMDisasmDispose() disposes of the disassembler specified by the context.
//
void LLVMDisasmDispose(LLVMDisasmContextRef DCR){
  LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
  delete DC;
}

/// \brief Emits the comments that are stored in \p DC comment stream.
/// Each comment in the comment stream must end with a newline.
static void emitComments(LLVMDisasmContext *DC,
                         formatted_raw_ostream &FormattedOS) {
  // Flush the stream before taking its content.
  DC->CommentStream.flush();
  StringRef Comments = DC->CommentsToEmit.str();
  // Get the default information for printing a comment.
  const MCAsmInfo *MAI = DC->getAsmInfo();
  const char *CommentBegin = MAI->getCommentString();
  unsigned CommentColumn = MAI->getCommentColumn();
  bool IsFirst = true;
  while (!Comments.empty()) {
    if (!IsFirst)
      FormattedOS << '\n';
    // Emit a line of comments.
    FormattedOS.PadToColumn(CommentColumn);
    size_t Position = Comments.find('\n');
    FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
    // Move after the newline character.
    Comments = Comments.substr(Position+1);
    IsFirst = false;
  }
  FormattedOS.flush();

  // Tell the comment stream that the vector changed underneath it.
  DC->CommentsToEmit.clear();
  DC->CommentStream.resync();
}

/// \brief Gets latency information for \p Inst form the itinerary
/// scheduling model, based on \p DC information.
/// \return The maximum expected latency over all the operands or -1
/// if no information are available.
static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
  const int NoInformationAvailable = -1;

  // Check if we have a CPU to get the itinerary information.
  if (DC->getCPU().empty())
    return NoInformationAvailable;

  // Get itinerary information.
  const MCSubtargetInfo *STI = DC->getSubtargetInfo();
  InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU());
  // Get the scheduling class of the requested instruction.
  const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
  unsigned SCClass = Desc.getSchedClass();

  int Latency = 0;
  for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd;
       ++OpIdx)
    Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx));

  return Latency;
}

/// \brief Gets latency information for \p Inst, based on \p DC information.
/// \return The maximum expected latency over all the definitions or -1
/// if no information are available.
static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
  // Try to compute scheduling information.
  const MCSubtargetInfo *STI = DC->getSubtargetInfo();
  const MCSchedModel SCModel = STI->getSchedModel();
  const int NoInformationAvailable = -1;

  // Check if we have a scheduling model for instructions.
  if (!SCModel.hasInstrSchedModel())
    // Try to fall back to the itinerary model if the scheduling model doesn't
    // have a scheduling table.  Note the default does not have a table.
    return getItineraryLatency(DC, Inst);

  // Get the scheduling class of the requested instruction.
  const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
  unsigned SCClass = Desc.getSchedClass();
  const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass);
  // Resolving the variant SchedClass requires an MI to pass to
  // SubTargetInfo::resolveSchedClass.
  if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
    return NoInformationAvailable;

  // Compute output latency.
  int Latency = 0;
  for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
       DefIdx != DefEnd; ++DefIdx) {
    // Lookup the definition's write latency in SubtargetInfo.
    const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc,
                                                                   DefIdx);
    Latency = std::max(Latency, WLEntry->Cycles);
  }

  return Latency;
}

/// \brief Emits latency information in DC->CommentStream for \p Inst, based
/// on the information available in \p DC.
static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
  int Latency = getLatency(DC, Inst);

  // Report only interesting latency.
  if (Latency < 2)
    return;

  DC->CommentStream << "Latency: " << Latency << '\n';
}

//
// LLVMDisasmInstruction() disassembles a single instruction using the
// disassembler context specified in the parameter DC.  The bytes of the
// instruction are specified in the parameter Bytes, and contains at least
// BytesSize number of bytes.  The instruction is at the address specified by
// the PC parameter.  If a valid instruction can be disassembled its string is
// returned indirectly in OutString which whos size is specified in the
// parameter OutStringSize.  This function returns the number of bytes in the
// instruction or zero if there was no valid instruction.  If this function
// returns zero the caller will have to pick how many bytes they want to step
// over by printing a .byte, .long etc. to continue.
//
size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
                             uint64_t BytesSize, uint64_t PC, char *OutString,
                             size_t OutStringSize){
  LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
  // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject.
  StringRef Data((const char*) Bytes, BytesSize);
  StringRefMemoryObject MemoryObject(Data, PC);

  uint64_t Size;
  MCInst Inst;
  const MCDisassembler *DisAsm = DC->getDisAsm();
  MCInstPrinter *IP = DC->getIP();
  MCDisassembler::DecodeStatus S;
  SmallVector<char, 64> InsnStr;
  raw_svector_ostream Annotations(InsnStr);
  S = DisAsm->getInstruction(Inst, Size, MemoryObject, PC,
                             /*REMOVE*/ nulls(), Annotations);
  switch (S) {
  case MCDisassembler::Fail:
  case MCDisassembler::SoftFail:
    // FIXME: Do something different for soft failure modes?
    return 0;

  case MCDisassembler::Success: {
    Annotations.flush();
    StringRef AnnotationsStr = Annotations.str();

    SmallVector<char, 64> InsnStr;
    raw_svector_ostream OS(InsnStr);
    formatted_raw_ostream FormattedOS(OS);
    IP->printInst(&Inst, FormattedOS, AnnotationsStr);

    if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency)
      emitLatency(DC, Inst);

    emitComments(DC, FormattedOS);
    OS.flush();

    assert(OutStringSize != 0 && "Output buffer cannot be zero size");
    size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());
    std::memcpy(OutString, InsnStr.data(), OutputSize);
    OutString[OutputSize] = '\0'; // Terminate string.

    return Size;
  }
  }
  llvm_unreachable("Invalid DecodeStatus!");
}

//
// LLVMSetDisasmOptions() sets the disassembler's options.  It returns 1 if it
// can set all the Options and 0 otherwise.
//
int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
  if (Options & LLVMDisassembler_Option_UseMarkup){
      LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
      MCInstPrinter *IP = DC->getIP();
      IP->setUseMarkup(1);
      DC->addOptions(LLVMDisassembler_Option_UseMarkup);
      Options &= ~LLVMDisassembler_Option_UseMarkup;
  }
  if (Options & LLVMDisassembler_Option_PrintImmHex){
      LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
      MCInstPrinter *IP = DC->getIP();
      IP->setPrintImmHex(1);
      DC->addOptions(LLVMDisassembler_Option_PrintImmHex);
      Options &= ~LLVMDisassembler_Option_PrintImmHex;
  }
  if (Options & LLVMDisassembler_Option_AsmPrinterVariant){
      LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
      // Try to set up the new instruction printer.
      const MCAsmInfo *MAI = DC->getAsmInfo();
      const MCInstrInfo *MII = DC->getInstrInfo();
      const MCRegisterInfo *MRI = DC->getRegisterInfo();
      const MCSubtargetInfo *STI = DC->getSubtargetInfo();
      int AsmPrinterVariant = MAI->getAssemblerDialect();
      AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0;
      MCInstPrinter *IP = DC->getTarget()->createMCInstPrinter(
          AsmPrinterVariant, *MAI, *MII, *MRI, *STI);
      if (IP) {
        DC->setIP(IP);
        DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant);
        Options &= ~LLVMDisassembler_Option_AsmPrinterVariant;
      }
  }
  if (Options & LLVMDisassembler_Option_SetInstrComments) {
    LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
    MCInstPrinter *IP = DC->getIP();
    IP->setCommentStream(DC->CommentStream);
    DC->addOptions(LLVMDisassembler_Option_SetInstrComments);
    Options &= ~LLVMDisassembler_Option_SetInstrComments;
  }
  if (Options & LLVMDisassembler_Option_PrintLatency) {
    LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
    DC->addOptions(LLVMDisassembler_Option_PrintLatency);
    Options &= ~LLVMDisassembler_Option_PrintLatency;
  }
  return (Options == 0);
}
<|endoftext|>


<commit_before>#include <common/buffer.h>
#include <common/endian.h>

#include <event/action.h>
#include <event/callback.h>
#include <event/event_callback.h>
#include <event/event_main.h>
#include <event/event_system.h>

#include <http/http_server_pipe.h>

#include <io/net/tcp_server.h>

#include <io/pipe/pipe.h>
#include <io/pipe/pipe_producer.h>
#include <io/pipe/splice.h>

#include <io/socket/simple_server.h>

#include <vis.h>

HTTPServerPipe::HTTPServerPipe(const LogHandle& log)
: PipeProducer(log),
  state_(GetStart),
  buffer_(),
  message_(),
  last_header_(),
  action_(NULL),
  callback_(NULL)
{ }

HTTPServerPipe::~HTTPServerPipe()
{
	ASSERT(action_ == NULL);
	ASSERT(callback_ == NULL);
}

Action *
HTTPServerPipe::message(HTTPMessageEventCallback *cb)
{
	ASSERT(action_ == NULL);
	ASSERT(callback_ == NULL);

	if (state_ == GotMessage || state_ == Error)
		return (schedule_callback(cb));

	callback_ = cb;
	return (cancellation(this, &HTTPServerPipe::cancel));
}

void
HTTPServerPipe::send_response(HTTPProtocol::Status status, Buffer *body, Buffer *headers)
{
	if (state_ == GotMessage || state_ == Error) {
		ASSERT(buffer_.empty());
	} else {
		if (!buffer_.empty()) {
			buffer_.clear();
		} else {
			ASSERT(status == HTTPProtocol::BadRequest);
			DEBUG(log_) << "Premature end-of-stream.";
		}
		state_ = Error; /* Process no more input.  */

		/*
		 * For state change to Error, we must schedule a
		 * callback.
		 */
		ASSERT(action_ == NULL);
		if (callback_ != NULL) {
			action_ = schedule_callback(callback_);
			callback_ = NULL;
		}
	}

	/*
	 * Format status line.
	 */
	Buffer response("HTTP/1.1 ");
	switch (status) {
	case HTTPProtocol::OK:
		response.append("200 OK");
		break;
	case HTTPProtocol::BadRequest:
		response.append("400 Bad Request");
		break;
	case HTTPProtocol::NotFound:
		response.append("404 Not Found");
		break;
	case HTTPProtocol::NotImplemented:
		response.append("501 Not Implemented");
		break;
	case HTTPProtocol::VersionNotSupported:
		response.append("505 Version Not Supported");
		break;
	default:
		NOTREACHED();
	}
	response.append("\r\n");

	/*
	 * Fill response headers.
	 */
	response.append("Server: " + (std::string)log_ + "\r\n");
	response.append("Transfer-encoding: identity\r\n");
	response.append("Connection: close\r\n");
	if (headers != NULL) {
		response.append(headers);
		headers->clear();
	}
	response.append("\r\n");

	/*
	 * Append body.  No encodings supported yet.
	 */
	response.append(body);
	body->clear();

	/*
	 * Output response and EOS.
	 *
	 * XXX Really want produce_eos(&response);
	 */
	produce(&response);
	ASSERT(response.empty());

	Buffer eos;
	produce(&eos);
}

void
HTTPServerPipe::send_response(HTTPProtocol::Status status, const std::string& body, const std::string& content_type)
{
	Buffer tmp(body);
	Buffer header("Content-type: " + content_type + "\r\n");
	send_response(status, &tmp, &header);
	ASSERT(tmp.empty());
}

void
HTTPServerPipe::cancel(void)
{
	if (action_ != NULL) {
		action_->cancel();
		action_ = NULL;

		ASSERT(callback_ == NULL);
	} else {
		ASSERT(callback_ != NULL);
		delete callback_;
		callback_ = NULL;
	}
}

Action *
HTTPServerPipe::schedule_callback(HTTPMessageEventCallback *cb)
{
	switch (state_) {
	case GotMessage:
		cb->param(Event::Done, message_);
		break;
	case Error:
		cb->param(Event::Error, HTTPProtocol::Message());
		break;
	default:
		NOTREACHED();
	}

	return (cb->schedule());
}

void
HTTPServerPipe::consume(Buffer *in)
{
	if (state_ == GotMessage || state_ == Error) {
		ASSERT(buffer_.empty());
		if (in->empty()) {
			DEBUG(log_) << "Got end-of-stream.";
			return;
		}

		/*
		 * XXX
		 * Really want a way to shut down input.
		 */
		if (state_ == GotMessage) {
			ERROR(log_) << "Client sent unexpected additional data after request.";
			state_ = Error;

			/*
			 * No need to schedule a callback for this state
			 * change, the change to GotMessage already did.
			 */
		} else {
			ERROR(log_) << "Client continuing to send gibberish.";
		}
		in->clear();
		return;
	}

	if (in->empty()) {
		send_response(HTTPProtocol::BadRequest, "Premature end of request.");
		return;
	}

	buffer_.append(in);
	in->clear();

	for (;;) {
		ASSERT(!buffer_.empty());

		Buffer line;
		unsigned pos;
		uint8_t found;
		if (!buffer_.find_any("\r\n", &pos, 0, &found)) {
			DEBUG(log_) << "Waiting for remainder of line.";
			return;
		}

		/*
		 * XXX
		 * We should pick line ending from the start line and require it to
		 * be consistent for remaining lines, rather than using find_any over
		 * and over, which is non-trivial.  Handling of the start line can be
		 * quite easily and cheaply before the loop.
		 */
		switch (found) {
		case '\r':
			/* CRLF line endings.  */
			ASSERT(buffer_.length() > pos);
			if (buffer_.length() == pos + 1) {
				DEBUG(log_) << "Carriage return at end of buffer, waiting for line feed.";
				return;
			}
			if (pos != 0)
				buffer_.moveout(&line, pos);
			buffer_.skip(1);
			if (buffer_.peek() != '\n') {
				ERROR(log_) << "Carriage return not followed by line feed.";
				send_response(HTTPProtocol::BadRequest, "Line includes embedded carriage return.");
				return;
			}
			buffer_.skip(1);
			break;
		case '\n':
			/* Unix line endings.  */
			buffer_.moveout(&line, pos);
			buffer_.skip(1);
			break;
		default:
			NOTREACHED();
		}

		if (state_ == GetStart) {
			ASSERT(message_.start_line_.empty());
			if (line.empty()) {
				ERROR(log_) << "Premature end of headers.";
				return;
			}
			message_.start_line_ = line;

			/*
			 * There are two kinds of request line.  The first has two
			 * words, the second has three.  Anything else is malformed.
			 *
			 * The first kind is HTTP/0.9.  The second kind can be
			 * anything, especially HTTP/1.0 and HTTP/1.1.
			 */
			std::vector<Buffer> words = line.split(' ', false);
			if (words.empty()) {
				send_response(HTTPProtocol::BadRequest, "Empty start line.");
				return;
			}

			if (words.size() == 3) {
				/*
				 * HTTP/1.0 or HTTP/1.1.  Get headers.
				 */
				state_ = GetHeaders;

				if (buffer_.empty())
					break;
				continue;
			}

			if (words.size() != 2) {
				/*
				 * Not HTTP/0.9.
				 */
				send_response(HTTPProtocol::BadRequest, "Too many request parameters.");
				return;
			}

			/*
			 * HTTP/0.9.  This is all we should get from the client.
			 */
			if (!buffer_.empty()) {
				send_response(HTTPProtocol::BadRequest, "Garbage after HTTP/0.9-style request.");
				return;
			}

			/*
			 * We have received the full message.  Process any
			 * pending callback.
			 */
			state_ = GotMessage;

			ASSERT(action_ == NULL);
			if (callback_ != NULL) {
				action_ = schedule_callback(callback_);
				callback_ = NULL;
			}
			return;
		}

		ASSERT(state_ == GetHeaders);
		ASSERT(!message_.start_line_.empty());

		/*
		 * Process end of headers!
		 */
		if (line.empty()) {
			if (!buffer_.empty()) {
				ERROR(log_) << "Client sent garbage after message.";
				send_response(HTTPProtocol::BadRequest, "Garbage after message.");
				return;
			}

			/*
			 * We have received the full message.  Process any
			 * pending callback.
			 */
			state_ = GotMessage;

			ASSERT(action_ == NULL);
			if (callback_ != NULL) {
				action_ = schedule_callback(callback_);
				callback_ = NULL;
			}
			return;
		}

		/*
		 * Process header.
		 */
		if (line.peek() == ' ') { /* XXX isspace? */
			/*
			 * Fold headers per RFC822.
			 *
			 * XXX Always forget how to handle leading whitespace.
			 */
			if (last_header_ == "") {
				send_response(HTTPProtocol::BadRequest, "Folded header sent before any others.");
				return;
			}

			message_.headers_[last_header_].back().append(line);
			if (buffer_.empty())
				break;
			continue;
		}

		if (!line.find(':', &pos)) {
			send_response(HTTPProtocol::BadRequest, "Empty header name.");
			return;
		}

		Buffer key;
		line.moveout(&key, pos);
		line.skip(1);

		Buffer value;
		while (!line.empty() && line.peek() == ' ')
			line.skip(1);
		value = line;

		std::string header;
		key.extract(header);

		message_.headers_[header].push_back(value);
		last_header_ = header;

		if (buffer_.empty())
			break;
	}
}
<commit_msg>Fix Unix line-endings.<commit_after>#include <common/buffer.h>
#include <common/endian.h>

#include <event/action.h>
#include <event/callback.h>
#include <event/event_callback.h>
#include <event/event_main.h>
#include <event/event_system.h>

#include <http/http_server_pipe.h>

#include <io/net/tcp_server.h>

#include <io/pipe/pipe.h>
#include <io/pipe/pipe_producer.h>
#include <io/pipe/splice.h>

#include <io/socket/simple_server.h>

#include <vis.h>

HTTPServerPipe::HTTPServerPipe(const LogHandle& log)
: PipeProducer(log),
  state_(GetStart),
  buffer_(),
  message_(),
  last_header_(),
  action_(NULL),
  callback_(NULL)
{ }

HTTPServerPipe::~HTTPServerPipe()
{
	ASSERT(action_ == NULL);
	ASSERT(callback_ == NULL);
}

Action *
HTTPServerPipe::message(HTTPMessageEventCallback *cb)
{
	ASSERT(action_ == NULL);
	ASSERT(callback_ == NULL);

	if (state_ == GotMessage || state_ == Error)
		return (schedule_callback(cb));

	callback_ = cb;
	return (cancellation(this, &HTTPServerPipe::cancel));
}

void
HTTPServerPipe::send_response(HTTPProtocol::Status status, Buffer *body, Buffer *headers)
{
	if (state_ == GotMessage || state_ == Error) {
		ASSERT(buffer_.empty());
	} else {
		if (!buffer_.empty()) {
			buffer_.clear();
		} else {
			ASSERT(status == HTTPProtocol::BadRequest);
			DEBUG(log_) << "Premature end-of-stream.";
		}
		state_ = Error; /* Process no more input.  */

		/*
		 * For state change to Error, we must schedule a
		 * callback.
		 */
		ASSERT(action_ == NULL);
		if (callback_ != NULL) {
			action_ = schedule_callback(callback_);
			callback_ = NULL;
		}
	}

	/*
	 * Format status line.
	 */
	Buffer response("HTTP/1.1 ");
	switch (status) {
	case HTTPProtocol::OK:
		response.append("200 OK");
		break;
	case HTTPProtocol::BadRequest:
		response.append("400 Bad Request");
		break;
	case HTTPProtocol::NotFound:
		response.append("404 Not Found");
		break;
	case HTTPProtocol::NotImplemented:
		response.append("501 Not Implemented");
		break;
	case HTTPProtocol::VersionNotSupported:
		response.append("505 Version Not Supported");
		break;
	default:
		NOTREACHED();
	}
	response.append("\r\n");

	/*
	 * Fill response headers.
	 */
	response.append("Server: " + (std::string)log_ + "\r\n");
	response.append("Transfer-encoding: identity\r\n");
	response.append("Connection: close\r\n");
	if (headers != NULL) {
		response.append(headers);
		headers->clear();
	}
	response.append("\r\n");

	/*
	 * Append body.  No encodings supported yet.
	 */
	response.append(body);
	body->clear();

	/*
	 * Output response and EOS.
	 *
	 * XXX Really want produce_eos(&response);
	 */
	produce(&response);
	ASSERT(response.empty());

	Buffer eos;
	produce(&eos);
}

void
HTTPServerPipe::send_response(HTTPProtocol::Status status, const std::string& body, const std::string& content_type)
{
	Buffer tmp(body);
	Buffer header("Content-type: " + content_type + "\r\n");
	send_response(status, &tmp, &header);
	ASSERT(tmp.empty());
}

void
HTTPServerPipe::cancel(void)
{
	if (action_ != NULL) {
		action_->cancel();
		action_ = NULL;

		ASSERT(callback_ == NULL);
	} else {
		ASSERT(callback_ != NULL);
		delete callback_;
		callback_ = NULL;
	}
}

Action *
HTTPServerPipe::schedule_callback(HTTPMessageEventCallback *cb)
{
	switch (state_) {
	case GotMessage:
		cb->param(Event::Done, message_);
		break;
	case Error:
		cb->param(Event::Error, HTTPProtocol::Message());
		break;
	default:
		NOTREACHED();
	}

	return (cb->schedule());
}

void
HTTPServerPipe::consume(Buffer *in)
{
	if (state_ == GotMessage || state_ == Error) {
		ASSERT(buffer_.empty());
		if (in->empty()) {
			DEBUG(log_) << "Got end-of-stream.";
			return;
		}

		/*
		 * XXX
		 * Really want a way to shut down input.
		 */
		if (state_ == GotMessage) {
			ERROR(log_) << "Client sent unexpected additional data after request.";
			state_ = Error;

			/*
			 * No need to schedule a callback for this state
			 * change, the change to GotMessage already did.
			 */
		} else {
			ERROR(log_) << "Client continuing to send gibberish.";
		}
		in->clear();
		return;
	}

	if (in->empty()) {
		send_response(HTTPProtocol::BadRequest, "Premature end of request.");
		return;
	}

	buffer_.append(in);
	in->clear();

	for (;;) {
		ASSERT(!buffer_.empty());

		Buffer line;
		unsigned pos;
		uint8_t found;
		if (!buffer_.find_any("\r\n", &pos, 0, &found)) {
			DEBUG(log_) << "Waiting for remainder of line.";
			return;
		}

		/*
		 * XXX
		 * We should pick line ending from the start line and require it to
		 * be consistent for remaining lines, rather than using find_any over
		 * and over, which is non-trivial.  Handling of the start line can be
		 * quite easily and cheaply before the loop.
		 */
		switch (found) {
		case '\r':
			/* CRLF line endings.  */
			ASSERT(buffer_.length() > pos);
			if (buffer_.length() == pos + 1) {
				DEBUG(log_) << "Carriage return at end of buffer, waiting for line feed.";
				return;
			}
			if (pos != 0)
				buffer_.moveout(&line, pos);
			buffer_.skip(1);
			if (buffer_.peek() != '\n') {
				ERROR(log_) << "Carriage return not followed by line feed.";
				send_response(HTTPProtocol::BadRequest, "Line includes embedded carriage return.");
				return;
			}
			buffer_.skip(1);
			break;
		case '\n':
			/* Unix line endings.  */
			if (pos != 0)
				buffer_.moveout(&line, pos);
			buffer_.skip(1);
			break;
		default:
			NOTREACHED();
		}

		if (state_ == GetStart) {
			ASSERT(message_.start_line_.empty());
			if (line.empty()) {
				ERROR(log_) << "Premature end of headers.";
				return;
			}
			message_.start_line_ = line;

			/*
			 * There are two kinds of request line.  The first has two
			 * words, the second has three.  Anything else is malformed.
			 *
			 * The first kind is HTTP/0.9.  The second kind can be
			 * anything, especially HTTP/1.0 and HTTP/1.1.
			 */
			std::vector<Buffer> words = line.split(' ', false);
			if (words.empty()) {
				send_response(HTTPProtocol::BadRequest, "Empty start line.");
				return;
			}

			if (words.size() == 3) {
				/*
				 * HTTP/1.0 or HTTP/1.1.  Get headers.
				 */
				state_ = GetHeaders;

				if (buffer_.empty())
					break;
				continue;
			}

			if (words.size() != 2) {
				/*
				 * Not HTTP/0.9.
				 */
				send_response(HTTPProtocol::BadRequest, "Too many request parameters.");
				return;
			}

			/*
			 * HTTP/0.9.  This is all we should get from the client.
			 */
			if (!buffer_.empty()) {
				send_response(HTTPProtocol::BadRequest, "Garbage after HTTP/0.9-style request.");
				return;
			}

			/*
			 * We have received the full message.  Process any
			 * pending callback.
			 */
			state_ = GotMessage;

			ASSERT(action_ == NULL);
			if (callback_ != NULL) {
				action_ = schedule_callback(callback_);
				callback_ = NULL;
			}
			return;
		}

		ASSERT(state_ == GetHeaders);
		ASSERT(!message_.start_line_.empty());

		/*
		 * Process end of headers!
		 */
		if (line.empty()) {
			if (!buffer_.empty()) {
				ERROR(log_) << "Client sent garbage after message.";
				send_response(HTTPProtocol::BadRequest, "Garbage after message.");
				return;
			}

			/*
			 * We have received the full message.  Process any
			 * pending callback.
			 */
			state_ = GotMessage;

			ASSERT(action_ == NULL);
			if (callback_ != NULL) {
				action_ = schedule_callback(callback_);
				callback_ = NULL;
			}
			return;
		}

		/*
		 * Process header.
		 */
		if (line.peek() == ' ') { /* XXX isspace? */
			/*
			 * Fold headers per RFC822.
			 *
			 * XXX Always forget how to handle leading whitespace.
			 */
			if (last_header_ == "") {
				send_response(HTTPProtocol::BadRequest, "Folded header sent before any others.");
				return;
			}

			message_.headers_[last_header_].back().append(line);
			if (buffer_.empty())
				break;
			continue;
		}

		if (!line.find(':', &pos)) {
			send_response(HTTPProtocol::BadRequest, "Empty header name.");
			return;
		}

		Buffer key;
		line.moveout(&key, pos);
		line.skip(1);

		Buffer value;
		while (!line.empty() && line.peek() == ' ')
			line.skip(1);
		value = line;

		std::string header;
		key.extract(header);

		message_.headers_[header].push_back(value);
		last_header_ = header;

		if (buffer_.empty())
			break;
	}
}
<|endoftext|>


<commit_before>//===-- DataflowDiagnostics.cpp - Emits diagnostics based on SIL analysis -===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "swift/Subsystems.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/Diagnostics.h"
#include "swift/AST/Expr.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILLocation.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILVisitor.h"

#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"

using namespace swift;

namespace {

template<typename...T, typename...U>
void diagnose(ASTContext &Context, SourceLoc loc, Diag<T...> diag,
              U &&...args) {
  Context.Diags.diagnose(loc,
                         diag, std::forward<U>(args)...);
}

static void diagnoseUnreachable(const SILInstruction *I,
                                ASTContext &Context) {
  if (auto *UI = dyn_cast<UnreachableInst>(I)){
    const SILBasicBlock *BB = UI->getParent();
    const SILFunction *F = BB->getParent();

    // The most common case of getting an unreachable instruction is a
    // missing return statement.
    SILLocation FLoc = F->getLocation();

    Type ResTy;

    // Should be an Expr as it's the parent of the basic block.
    if (const FuncExpr *FExpr = FLoc.getAs<FuncExpr>())
      ResTy = FExpr->getResultType(Context);
    else {
      // FIXME: Not all closure types have the result type getter right
      // now.
      return;
    }

    // If the function does not return void, issue the diagnostic.
    if (!ResTy->isVoid()) {
      SILLocation L = UI->getLoc();
      if (L)
        diagnose(Context,
                 L.getEndSourceLoc(),
                 diag::missing_return, ResTy.getString());
    }
  }
}

}; // end of anonymous namespace

void swift::emitSILDataflowDiagnostics(const SILModule *M) {
  for (auto &Fn : *M)
    for (auto &BB : Fn)
      for (auto &I : BB)
        diagnoseUnreachable(&I, M->getASTContext());
}
<commit_msg>[SIL diagnostics] Teach "missing return" warning about noreturn attribute<commit_after>//===-- DataflowDiagnostics.cpp - Emits diagnostics based on SIL analysis -===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "swift/Subsystems.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/Diagnostics.h"
#include "swift/AST/Expr.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILLocation.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILVisitor.h"

#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"

using namespace swift;

namespace {

template<typename...T, typename...U>
void diagnose(ASTContext &Context, SourceLoc loc, Diag<T...> diag,
              U &&...args) {
  Context.Diags.diagnose(loc,
                         diag, std::forward<U>(args)...);
}

static void diagnoseUnreachable(const SILInstruction *I,
                                ASTContext &Context) {
  if (auto *UI = dyn_cast<UnreachableInst>(I)){
    const SILBasicBlock *BB = UI->getParent();
    const SILFunction *F = BB->getParent();

    // The most common case of getting an unreachable instruction is a
    // missing return statement.
    SILLocation FLoc = F->getLocation();

    Type ResTy;

    // Should be an Expr as it's the parent of the basic block.
    if (const FuncExpr *FExpr = FLoc.getAs<FuncExpr>()) {
      ResTy = FExpr->getResultType(Context);
      if (AnyFunctionType *T = FExpr->getType()->castTo<AnyFunctionType>()) {
        if (T->isNoReturn())
          return;
      }
    } else {
      // FIXME: Not all closure types have the result type getter right
      // now.
      return;
    }

    // If the function does not return void, issue the diagnostic.
    if (!ResTy->isVoid()) {
      SILLocation L = UI->getLoc();
      if (L)
        diagnose(Context,
                 L.getEndSourceLoc(),
                 diag::missing_return, ResTy.getString());
    }
  }
}

}; // end of anonymous namespace

void swift::emitSILDataflowDiagnostics(const SILModule *M) {
  for (auto &Fn : *M)
    for (auto &BB : Fn)
      for (auto &I : BB)
        diagnoseUnreachable(&I, M->getASTContext());
}
<|endoftext|>


<commit_before>//===- PartialInlining.cpp - Inline parts of functions --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass performs partial inlining, typically by inlining an if statement
// that surrounds the body of the function.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "partialinlining"
#include "llvm/Transforms/IPO.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/FunctionUtils.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/CFG.h"
using namespace llvm;

STATISTIC(NumPartialInlined, "Number of functions partially inlined");

namespace {
  struct VISIBILITY_HIDDEN PartialInliner : public ModulePass {
    virtual void getAnalysisUsage(AnalysisUsage &AU) const { }
    static char ID; // Pass identification, replacement for typeid
    PartialInliner() : ModulePass(&ID) {}

    bool runOnModule(Module& M);

  private:
    Function* unswitchFunction(Function* F);
  };
}

char PartialInliner::ID = 0;
static RegisterPass<PartialInliner> X("partial-inliner", "Partial Inliner");

ModulePass* llvm::createPartialInliningPass() { return new PartialInliner(); }

Function* PartialInliner::unswitchFunction(Function* F) {
  // First, verify that this function is an unswitching candidate...
  BasicBlock* entryBlock = F->begin();
  if (!isa<BranchInst>(entryBlock->getTerminator()))
    return 0;

  BasicBlock* returnBlock = 0;
  BasicBlock* nonReturnBlock = 0;
  unsigned returnCount = 0;
  for (succ_iterator SI = succ_begin(entryBlock), SE = succ_end(entryBlock);
       SI != SE; ++SI)
    if (isa<ReturnInst>((*SI)->getTerminator())) {
      returnBlock = *SI;
      returnCount++;
    } else
      nonReturnBlock = *SI;

  if (returnCount != 1)
    return 0;

  // Clone the function, so that we can hack away on it.
  DenseMap<const Value*, Value*> ValueMap;
  Function* duplicateFunction = CloneFunction(F, ValueMap);
  duplicateFunction->setLinkage(GlobalValue::InternalLinkage);
  F->getParent()->getFunctionList().push_back(duplicateFunction);
  BasicBlock* newEntryBlock = cast<BasicBlock>(ValueMap[entryBlock]);
  BasicBlock* newReturnBlock = cast<BasicBlock>(ValueMap[returnBlock]);
  BasicBlock* newNonReturnBlock = cast<BasicBlock>(ValueMap[nonReturnBlock]);

  // Go ahead and update all uses to the duplicate, so that we can just
  // use the inliner functionality when we're done hacking.
  F->replaceAllUsesWith(duplicateFunction);

  // Special hackery is needed with PHI nodes that have inputs from more than
  // one extracted block.  For simplicity, just split the PHIs into a two-level
  // sequence of PHIs, some of which will go in the extracted region, and some
  // of which will go outside.
  BasicBlock* preReturn = newReturnBlock;
  newReturnBlock = newReturnBlock->splitBasicBlock(
                                              newReturnBlock->getFirstNonPHI());
  BasicBlock::iterator I = preReturn->begin();
  BasicBlock::iterator Ins = newReturnBlock->begin();
  while (I != preReturn->end()) {
    PHINode* OldPhi = dyn_cast<PHINode>(I);
    if (!OldPhi) break;

    PHINode* retPhi = PHINode::Create(OldPhi->getType(), "", Ins);
    OldPhi->replaceAllUsesWith(retPhi);
    Ins = newReturnBlock->getFirstNonPHI();

    retPhi->addIncoming(I, preReturn);
    retPhi->addIncoming(OldPhi->getIncomingValueForBlock(newEntryBlock),
                        newEntryBlock);
    OldPhi->removeIncomingValue(newEntryBlock);

    ++I;
  }
  newEntryBlock->getTerminator()->replaceUsesOfWith(preReturn, newReturnBlock);

  // Gather up the blocks that we're going to extract.
  std::vector<BasicBlock*> toExtract;
  toExtract.push_back(newNonReturnBlock);
  for (Function::iterator FI = duplicateFunction->begin(),
       FE = duplicateFunction->end(); FI != FE; ++FI)
    if (&*FI != newEntryBlock && &*FI != newReturnBlock &&
        &*FI != newNonReturnBlock)
      toExtract.push_back(FI);

  // The CodeExtractor needs a dominator tree.
  DominatorTree DT;
  DT.runOnFunction(*duplicateFunction);

  // Extract the body of the the if.
  Function* extractedFunction = ExtractCodeRegion(DT, toExtract);

  // Inline the top-level if test into all callers.
  std::vector<User*> Users(duplicateFunction->use_begin(),
                           duplicateFunction->use_end());
  for (std::vector<User*>::iterator UI = Users.begin(), UE = Users.end();
       UI != UE; ++UI)
    if (CallInst* CI = dyn_cast<CallInst>(*UI))
      InlineFunction(CI);
    else if (InvokeInst* II = dyn_cast<InvokeInst>(*UI))
      InlineFunction(II);

  // Ditch the duplicate, since we're done with it, and rewrite all remaining
  // users (function pointers, etc.) back to the original function.
  duplicateFunction->replaceAllUsesWith(F);
  duplicateFunction->eraseFromParent();

  ++NumPartialInlined;

  return extractedFunction;
}

bool PartialInliner::runOnModule(Module& M) {
  std::vector<Function*> worklist;
  worklist.reserve(M.size());
  for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)
    if (!FI->use_empty() && !FI->isDeclaration())
    worklist.push_back(&*FI);

  bool changed = false;
  while (!worklist.empty()) {
    Function* currFunc = worklist.back();
    worklist.pop_back();

    if (currFunc->use_empty()) continue;

    bool recursive = false;
    for (Function::use_iterator UI = currFunc->use_begin(),
         UE = currFunc->use_end(); UI != UE; ++UI)
      if (Instruction* I = dyn_cast<Instruction>(UI))
        if (I->getParent()->getParent() == currFunc) {
          recursive = true;
          break;
        }
    if (recursive) continue;

    if (Function* newFunc = unswitchFunction(currFunc)) {
      worklist.push_back(newFunc);
      changed = true;
    }

  }

  return changed;
}<commit_msg>Add newline at end of file.<commit_after>//===- PartialInlining.cpp - Inline parts of functions --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass performs partial inlining, typically by inlining an if statement
// that surrounds the body of the function.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "partialinlining"
#include "llvm/Transforms/IPO.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/FunctionUtils.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/CFG.h"
using namespace llvm;

STATISTIC(NumPartialInlined, "Number of functions partially inlined");

namespace {
  struct VISIBILITY_HIDDEN PartialInliner : public ModulePass {
    virtual void getAnalysisUsage(AnalysisUsage &AU) const { }
    static char ID; // Pass identification, replacement for typeid
    PartialInliner() : ModulePass(&ID) {}

    bool runOnModule(Module& M);

  private:
    Function* unswitchFunction(Function* F);
  };
}

char PartialInliner::ID = 0;
static RegisterPass<PartialInliner> X("partial-inliner", "Partial Inliner");

ModulePass* llvm::createPartialInliningPass() { return new PartialInliner(); }

Function* PartialInliner::unswitchFunction(Function* F) {
  // First, verify that this function is an unswitching candidate...
  BasicBlock* entryBlock = F->begin();
  if (!isa<BranchInst>(entryBlock->getTerminator()))
    return 0;

  BasicBlock* returnBlock = 0;
  BasicBlock* nonReturnBlock = 0;
  unsigned returnCount = 0;
  for (succ_iterator SI = succ_begin(entryBlock), SE = succ_end(entryBlock);
       SI != SE; ++SI)
    if (isa<ReturnInst>((*SI)->getTerminator())) {
      returnBlock = *SI;
      returnCount++;
    } else
      nonReturnBlock = *SI;

  if (returnCount != 1)
    return 0;

  // Clone the function, so that we can hack away on it.
  DenseMap<const Value*, Value*> ValueMap;
  Function* duplicateFunction = CloneFunction(F, ValueMap);
  duplicateFunction->setLinkage(GlobalValue::InternalLinkage);
  F->getParent()->getFunctionList().push_back(duplicateFunction);
  BasicBlock* newEntryBlock = cast<BasicBlock>(ValueMap[entryBlock]);
  BasicBlock* newReturnBlock = cast<BasicBlock>(ValueMap[returnBlock]);
  BasicBlock* newNonReturnBlock = cast<BasicBlock>(ValueMap[nonReturnBlock]);

  // Go ahead and update all uses to the duplicate, so that we can just
  // use the inliner functionality when we're done hacking.
  F->replaceAllUsesWith(duplicateFunction);

  // Special hackery is needed with PHI nodes that have inputs from more than
  // one extracted block.  For simplicity, just split the PHIs into a two-level
  // sequence of PHIs, some of which will go in the extracted region, and some
  // of which will go outside.
  BasicBlock* preReturn = newReturnBlock;
  newReturnBlock = newReturnBlock->splitBasicBlock(
                                              newReturnBlock->getFirstNonPHI());
  BasicBlock::iterator I = preReturn->begin();
  BasicBlock::iterator Ins = newReturnBlock->begin();
  while (I != preReturn->end()) {
    PHINode* OldPhi = dyn_cast<PHINode>(I);
    if (!OldPhi) break;

    PHINode* retPhi = PHINode::Create(OldPhi->getType(), "", Ins);
    OldPhi->replaceAllUsesWith(retPhi);
    Ins = newReturnBlock->getFirstNonPHI();

    retPhi->addIncoming(I, preReturn);
    retPhi->addIncoming(OldPhi->getIncomingValueForBlock(newEntryBlock),
                        newEntryBlock);
    OldPhi->removeIncomingValue(newEntryBlock);

    ++I;
  }
  newEntryBlock->getTerminator()->replaceUsesOfWith(preReturn, newReturnBlock);

  // Gather up the blocks that we're going to extract.
  std::vector<BasicBlock*> toExtract;
  toExtract.push_back(newNonReturnBlock);
  for (Function::iterator FI = duplicateFunction->begin(),
       FE = duplicateFunction->end(); FI != FE; ++FI)
    if (&*FI != newEntryBlock && &*FI != newReturnBlock &&
        &*FI != newNonReturnBlock)
      toExtract.push_back(FI);

  // The CodeExtractor needs a dominator tree.
  DominatorTree DT;
  DT.runOnFunction(*duplicateFunction);

  // Extract the body of the the if.
  Function* extractedFunction = ExtractCodeRegion(DT, toExtract);

  // Inline the top-level if test into all callers.
  std::vector<User*> Users(duplicateFunction->use_begin(),
                           duplicateFunction->use_end());
  for (std::vector<User*>::iterator UI = Users.begin(), UE = Users.end();
       UI != UE; ++UI)
    if (CallInst* CI = dyn_cast<CallInst>(*UI))
      InlineFunction(CI);
    else if (InvokeInst* II = dyn_cast<InvokeInst>(*UI))
      InlineFunction(II);

  // Ditch the duplicate, since we're done with it, and rewrite all remaining
  // users (function pointers, etc.) back to the original function.
  duplicateFunction->replaceAllUsesWith(F);
  duplicateFunction->eraseFromParent();

  ++NumPartialInlined;

  return extractedFunction;
}

bool PartialInliner::runOnModule(Module& M) {
  std::vector<Function*> worklist;
  worklist.reserve(M.size());
  for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)
    if (!FI->use_empty() && !FI->isDeclaration())
    worklist.push_back(&*FI);

  bool changed = false;
  while (!worklist.empty()) {
    Function* currFunc = worklist.back();
    worklist.pop_back();

    if (currFunc->use_empty()) continue;

    bool recursive = false;
    for (Function::use_iterator UI = currFunc->use_begin(),
         UE = currFunc->use_end(); UI != UE; ++UI)
      if (Instruction* I = dyn_cast<Instruction>(UI))
        if (I->getParent()->getParent() == currFunc) {
          recursive = true;
          break;
        }
    if (recursive) continue;

    if (Function* newFunc = unswitchFunction(currFunc)) {
      worklist.push_back(newFunc);
      changed = true;
    }

  }

  return changed;
}
<|endoftext|>


<commit_before>//===- LoopRotation.cpp - Loop Rotation Pass ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Devang Patel and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Loop Rotation Pass.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "loop-rotate"

#include "llvm/Transforms/Scalar.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallVector.h"

using namespace llvm;

#define MAX_HEADER_SIZE 16

STATISTIC(NumRotated, "Number of loops rotated");
namespace {

  class VISIBILITY_HIDDEN RenameData {
  public:
    RenameData(Instruction *O, Instruction *P, Instruction *H)
      : Original(O), PreHeader(P), Header(H) { }
  public:
    Instruction *Original; // Original instruction
    Instruction *PreHeader; // New pre-header replacement
    Instruction *Header; // New header replacement
  };

  class VISIBILITY_HIDDEN LoopRotate : public LoopPass {

  public:

    // Rotate Loop L as many times as possible. Return true if
    // loop is rotated at least once.
    bool runOnLoop(Loop *L, LPPassManager &LPM);

    // LCSSA form makes instruction renaming easier.
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequiredID(LCSSAID);
      AU.addPreservedID(LCSSAID);
    }

    // Helper functions

    /// Do actual work
    bool rotateLoop(Loop *L, LPPassManager &LPM);

    /// Initialize local data
    void initialize();

    /// Make sure all Exit block PHINodes have required incoming values.
    /// If incoming value is constant or defined outside the loop then
    /// PHINode may not have an entry for new pre-header.
    void  updateExitBlock();

    /// Return true if this instruction is used outside original header.
    bool usedOutsideOriginalHeader(Instruction *In);

    /// Find Replacement information for instruction. Return NULL if it is
    /// not available.
    RenameData *findReplacementData(Instruction *I);

  private:

    Loop *L;
    BasicBlock *OrigHeader;
    BasicBlock *OrigPreHeader;
    BasicBlock *OrigLatch;
    BasicBlock *NewHeader;
    BasicBlock *NewPreHeader;
    BasicBlock *Exit;

    SmallVector<RenameData, MAX_HEADER_SIZE> LoopHeaderInfo;
  };

  RegisterPass<LoopRotate> X ("loop-rotate", "Rotate Loops");
}

LoopPass *llvm::createLoopRotatePass() { return new LoopRotate(); }

/// Rotate Loop L as many times as possible. Return true if
/// loop is rotated at least once.
bool LoopRotate::runOnLoop(Loop *Lp, LPPassManager &LPM) {

  bool RotatedOneLoop = false;
  initialize();

  // One loop can be rotated multiple times.
  while (rotateLoop(Lp,LPM)) {
    RotatedOneLoop = true;
    initialize();
  }

  return RotatedOneLoop;
}

/// Rotate loop LP. Return true if it loop is rotated.
bool LoopRotate::rotateLoop(Loop *Lp, LPPassManager &LPM) {

  L = Lp;

  OrigHeader =  L->getHeader();
  OrigPreHeader = L->getLoopPreheader();
  OrigLatch = L->getLoopLatch();

  // If loop has only one block then there is not much to rotate.
  if (L->getBlocks().size() == 1)
    return false;

  if (!OrigHeader || !OrigLatch || !OrigPreHeader)
    return false;

  // If loop header is not one of the loop exit block then
  // either this loop is already rotated or it is not
  // suitable for loop rotation transformations.
  if (!L->isLoopExit(OrigHeader))
    return false;

  BranchInst *BI = dyn_cast<BranchInst>(OrigHeader->getTerminator());
  if (!BI)
    return false;
  assert (BI->isConditional() && "Branch Instruction is not condiitional");

  // Updating PHInodes in loops with multiple exits adds complexity.
  // Keep it simple, and restrict loop rotation to loops with one exit only.
  // In future, lift this restriction and support for multiple exits if
  // required.
  std::vector<BasicBlock *> ExitBlocks;
  L->getExitBlocks(ExitBlocks);
  if (ExitBlocks.size() > 1)
    return false;

  // Find new Loop header. NewHeader is a Header's one and only successor
  // that is inside loop.  Header's other successor is out side the
  // loop. Otherwise loop is not suitable for rotation.
  Exit = BI->getSuccessor(0);
  NewHeader = BI->getSuccessor(1);
  if (L->contains(Exit))
    std::swap(Exit, NewHeader);
  assert (NewHeader && "Unable to determine new loop header");
  assert(L->contains(NewHeader) && !L->contains(Exit) &&
         "Unable to determine loop header and exit blocks");

  // Check size of original header and reject
  // loop if it is very big.
  if (OrigHeader->getInstList().size() > MAX_HEADER_SIZE)
    return false;

  // Now, this loop is suitable for rotation.

  // Copy PHI nodes and other instructions from original header
  // into new pre-header. Unlike original header, new pre-header is
  // not a member of loop. New pre-header has only one predecessor,
  // that is original loop pre-header.
  //
  // New loop header is one and only successor of original header that
  // is inside the loop. All other original header successors are outside
  // the loop. Copy PHI Nodes from original header into new loop header.
  // Add second incoming value, from new loop pre-header into these phi
  // nodes. If a value defined in original header is used outside original
  // header then new loop header will need new phi nodes with two incoming
  // values, one definition from original header and second definition is
  // from new loop pre-header (which is a clone of original header definition).

  NewPreHeader = new BasicBlock("bb.nph", OrigHeader->getParent(), OrigHeader);
  BasicBlock::iterator I = OrigHeader->begin(), E = OrigHeader->end();
  for (; I != E; ++I) {
    Instruction *In = I;

    PHINode *PN = dyn_cast<PHINode>(I);
    if (!PN)
      break;

    // Create new PHI node with one value incoming from OrigPreHeader.
    // NewPreHeader has only one predecessor, OrigPreHeader.
    PHINode *NPH = new PHINode(In->getType(), In->getName());
    NPH->addIncoming(PN->getIncomingValueForBlock(OrigPreHeader),
                     OrigPreHeader);
    NewPreHeader->getInstList().push_back(NPH);

    // Create new PHI node with two incoming values for NewHeader.
    // One incoming value is from OrigLatch (through OrigHeader) and
    // second incoming value is from NewPreHeader.
    PHINode *NH = new PHINode(In->getType(), In->getName());
    NH->addIncoming(PN->getIncomingValueForBlock(OrigLatch), OrigHeader);
    NH->addIncoming(NPH, NewPreHeader);
    NewHeader->getInstList().push_front(NH);

    // "In" can be replaced by NPH or NH at various places.
    LoopHeaderInfo.push_back(RenameData(In, NPH, NH));
  }

  // Now, handle non-phi instructions.
  for (; I != E; ++I) {
    Instruction *In = I;

    assert (!isa<PHINode>(In) && "PHINode is not expected here");
    // This is not a PHI instruction. Insert its clone into NewPreHeader.
    // If this instruction is using a value from same basic block then
    // update it to use value from cloned instruction.
    Instruction *C = In->clone();
    C->setName(In->getName());
    NewPreHeader->getInstList().push_back(C);

    // If this instruction is used outside this basic block then
    // create new PHINode for this instruction.
    Instruction *NewHeaderReplacement = NULL;
    if (usedOutsideOriginalHeader(In)) {
      PHINode *PN = new PHINode(In->getType(), In->getName());
      PN->addIncoming(In, OrigHeader);
      PN->addIncoming(C, NewPreHeader);
      NewHeader->getInstList().push_front(PN);
      NewHeaderReplacement = PN;
    }

    // "In" can be replaced by NPH or NH at various places.
    LoopHeaderInfo.push_back(RenameData(In, C, NewHeaderReplacement));
  }

  // Update new pre-header.
  // Rename values that are defined in original header to reflects values
  // defined in new pre-header.
  for (SmallVector<RenameData, MAX_HEADER_SIZE>::iterator
         I = LoopHeaderInfo.begin(), E = LoopHeaderInfo.end(); I != E; ++I) {

    RenameData ILoopHeaderInfo = (*I);
    Instruction *In = ILoopHeaderInfo.Original;
    Instruction *C = ILoopHeaderInfo.PreHeader;

    if (C->getParent() != NewPreHeader)
      continue;

    // PHINodes uses value from pre-header predecessors.
    if (isa<PHINode>(In))
      continue;

    for (unsigned opi = 0; opi < In->getNumOperands(); ++opi) {
      if (Instruction *OpPhi = dyn_cast<PHINode>(In->getOperand(opi))) {
        if (RenameData *D = findReplacementData(OpPhi))
          C->setOperand(opi, D->PreHeader);
      }
      else if (Instruction *OpInsn =
               dyn_cast<Instruction>(In->getOperand(opi))) {
        if (RenameData *D = findReplacementData(OpInsn))
          C->setOperand(opi, D->PreHeader);
      }
    }
  }

  // Rename uses of original header instructions to reflect their new
  // definitions (either from new pre-header node or from newly created
  // new header PHINodes.
  //
  // Original header instructions are used in
  // 1) Original header:
  //
  //    If instruction is used in non-phi instructions then it is using
  //    defintion from original heder iteself. Do not replace this use
  //    with definition from new header or new pre-header.
  //
  //    If instruction is used in phi node then it is an incoming
  //    value. Rename its use to reflect new definition from new-preheader
  //    or new header.
  //
  // 2) Inside loop but not in original header
  //
  //    Replace this use to reflect definition from new header.
  for (SmallVector<RenameData, MAX_HEADER_SIZE>::iterator
         I = LoopHeaderInfo.begin(), E = LoopHeaderInfo.end(); I != E; ++I) {

    RenameData ILoopHeaderInfo = (*I);
    if (!ILoopHeaderInfo.Header)
      continue;

    Instruction *OldPhi = ILoopHeaderInfo.Original;
    Instruction *NewPhi = ILoopHeaderInfo.Header;

    // Before replacing uses, collect them first, so that iterator is
    // not invalidated.
    SmallVector<Instruction *, 16> AllUses;
    for (Value::use_iterator UI = OldPhi->use_begin(), UE = OldPhi->use_end();
         UI != UE; ++UI ) {
      Instruction *U = cast<Instruction>(UI);
      AllUses.push_back(U);
    }

    for (SmallVector<Instruction *, 16>::iterator UI = AllUses.begin(),
           UE = AllUses.end(); UI != UE; ++UI) {
      Instruction *U = *UI;
      BasicBlock *Parent = U->getParent();

      // Used inside original header
      if (Parent == OrigHeader) {
        // Do not rename uses inside original header non-phi instructions.
        if (!isa<PHINode>(U))
          continue;
        PHINode *PU = dyn_cast<PHINode>(U);
        // Do not rename uses inside original header phi nodes, if the
        // incoming value is for new header.
        if (PU->getBasicBlockIndex(NewHeader) != -1
            && PU->getIncomingValueForBlock(NewHeader) == U)
          continue;

       U->replaceUsesOfWith(OldPhi, NewPhi);
       continue;
      }

      // Used inside loop, but not in original header.
      if (L->contains(U->getParent())) {
        if (U != NewPhi )
          U->replaceUsesOfWith(OldPhi, NewPhi);
        continue;
      }

      // Used inside Exit Block. Since we are in LCSSA form, U must be PHINode.
      assert ( U->getParent() == Exit && "Need to propagate new PHI into Exit blocks");
      assert (isa<PHINode>(U) && "Use in Exit Block that is not PHINode");

      PHINode *UPhi = cast<PHINode>(U);

      // UPhi already has one incoming argument from original header.
      // Add second incoming argument from new Pre header.

      UPhi->addIncoming(ILoopHeaderInfo.PreHeader, NewPreHeader);
    }
  }

  /// Make sure all Exit block PHINodes have required incoming values.
  updateExitBlock();

  // Update CFG

  // Removing incoming branch from loop preheader to original header.
  // Now original header is inside the loop.
  OrigHeader->removePredecessor(OrigPreHeader);

  // Establish NewPreHeader as loop preheader. Add unconditional branch
  // from original loop pre-header to new loop pre-header. Add NewPreHEader
  // in loop nest.
  BranchInst *PH_BI = cast<BranchInst>(OrigPreHeader->getTerminator());
  PH_BI->setSuccessor(0, NewPreHeader);
  LoopInfo &LI = LPM.getAnalysis<LoopInfo>();
  if (Loop *PL = LI.getLoopFor(OrigPreHeader))
    PL->addBasicBlockToLoop(NewPreHeader, LI);

  // Make NewHeader as the new header for the loop.
  L->moveToHeader(NewHeader);

  NumRotated++;
  return true;
}

/// Make sure all Exit block PHINodes have required incoming values.
/// If incoming value is constant or defined outside the loop then
/// PHINode may not have an entry for new pre-header.
void LoopRotate::updateExitBlock() {

  for (BasicBlock::iterator I = Exit->begin(), E = Exit->end();
       I != E; ++I) {

    if (!isa<PHINode>(I))
      break;

    PHINode *PN = dyn_cast<PHINode>(I);

    if (PN->getBasicBlockIndex(NewPreHeader) == -1) {
      Value *V = PN->getIncomingValueForBlock(OrigHeader);
      if (isa<Constant>(V))
        PN->addIncoming(V, NewPreHeader);
      else {
        RenameData *ILoopHeaderInfo = findReplacementData(cast<Instruction>(V));
        assert (ILoopHeaderInfo && ILoopHeaderInfo->PreHeader && "Missing New Preheader Instruction");
        PN->addIncoming(ILoopHeaderInfo->PreHeader, NewPreHeader);
      }
    }
  }
}

/// Initialize local data
void LoopRotate::initialize() {
  L = NULL;
  OrigHeader = NULL;
  OrigPreHeader = NULL;
  NewHeader = NULL;
  NewPreHeader = NULL;
  Exit = NULL;

  LoopHeaderInfo.clear();
}

/// Return true if this instruction is used outside original header.
bool LoopRotate::usedOutsideOriginalHeader(Instruction *In) {

  for (Value::use_iterator UI = In->use_begin(), UE = In->use_end();
       UI != UE; ++UI) {
    Instruction *U = cast<Instruction>(UI);
    if (U->getParent() != OrigHeader) {
      if (L->contains(U->getParent()))
        return true;
    }
  }

  return false;
}

/// Find Replacement information for instruction. Return NULL if it is
/// not available.
RenameData *LoopRotate::findReplacementData(Instruction *In) {

  // Since LoopHeaderInfo is small, linear walk is OK.
  for (SmallVector<RenameData, MAX_HEADER_SIZE>::iterator
         I = LoopHeaderInfo.begin(), E = LoopHeaderInfo.end(); I != E; ++I)
    if ((*I).Original == In)
      return &(*I);

  return NULL;
}
<commit_msg>More cosmetic changes.<commit_after>//===- LoopRotation.cpp - Loop Rotation Pass ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Devang Patel and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Loop Rotation Pass.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "loop-rotate"

#include "llvm/Transforms/Scalar.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallVector.h"

using namespace llvm;

#define MAX_HEADER_SIZE 16

STATISTIC(NumRotated, "Number of loops rotated");
namespace {

  class VISIBILITY_HIDDEN RenameData {
  public:
    RenameData(Instruction *O, Instruction *P, Instruction *H)
      : Original(O), PreHeader(P), Header(H) { }
  public:
    Instruction *Original; // Original instruction
    Instruction *PreHeader; // New pre-header replacement
    Instruction *Header; // New header replacement
  };

  class VISIBILITY_HIDDEN LoopRotate : public LoopPass {

  public:

    // Rotate Loop L as many times as possible. Return true if
    // loop is rotated at least once.
    bool runOnLoop(Loop *L, LPPassManager &LPM);

    // LCSSA form makes instruction renaming easier.
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequiredID(LCSSAID);
      AU.addPreservedID(LCSSAID);
    }

    // Helper functions

    /// Do actual work
    bool rotateLoop(Loop *L, LPPassManager &LPM);

    /// Initialize local data
    void initialize();

    /// Make sure all Exit block PHINodes have required incoming values.
    /// If incoming value is constant or defined outside the loop then
    /// PHINode may not have an entry for new pre-header.
    void  updateExitBlock();

    /// Return true if this instruction is used outside original header.
    bool usedOutsideOriginalHeader(Instruction *In);

    /// Find Replacement information for instruction. Return NULL if it is
    /// not available.
    RenameData *findReplacementData(Instruction *I);

  private:

    Loop *L;
    BasicBlock *OrigHeader;
    BasicBlock *OrigPreHeader;
    BasicBlock *OrigLatch;
    BasicBlock *NewHeader;
    BasicBlock *NewPreHeader;
    BasicBlock *Exit;

    SmallVector<RenameData, MAX_HEADER_SIZE> LoopHeaderInfo;
  };

  RegisterPass<LoopRotate> X ("loop-rotate", "Rotate Loops");
}

LoopPass *llvm::createLoopRotatePass() { return new LoopRotate(); }

/// Rotate Loop L as many times as possible. Return true if
/// loop is rotated at least once.
bool LoopRotate::runOnLoop(Loop *Lp, LPPassManager &LPM) {

  bool RotatedOneLoop = false;
  initialize();

  // One loop can be rotated multiple times.
  while (rotateLoop(Lp,LPM)) {
    RotatedOneLoop = true;
    initialize();
  }

  return RotatedOneLoop;
}

/// Rotate loop LP. Return true if it loop is rotated.
bool LoopRotate::rotateLoop(Loop *Lp, LPPassManager &LPM) {

  L = Lp;

  OrigHeader =  L->getHeader();
  OrigPreHeader = L->getLoopPreheader();
  OrigLatch = L->getLoopLatch();

  // If loop has only one block then there is not much to rotate.
  if (L->getBlocks().size() == 1)
    return false;

  if (!OrigHeader || !OrigLatch || !OrigPreHeader)
    return false;

  // If loop header is not one of the loop exit block then
  // either this loop is already rotated or it is not
  // suitable for loop rotation transformations.
  if (!L->isLoopExit(OrigHeader))
    return false;

  BranchInst *BI = dyn_cast<BranchInst>(OrigHeader->getTerminator());
  if (!BI)
    return false;
  assert (BI->isConditional() && "Branch Instruction is not condiitional");

  // Updating PHInodes in loops with multiple exits adds complexity.
  // Keep it simple, and restrict loop rotation to loops with one exit only.
  // In future, lift this restriction and support for multiple exits if
  // required.
  std::vector<BasicBlock *> ExitBlocks;
  L->getExitBlocks(ExitBlocks);
  if (ExitBlocks.size() > 1)
    return false;

  // Find new Loop header. NewHeader is a Header's one and only successor
  // that is inside loop.  Header's other successor is out side the
  // loop. Otherwise loop is not suitable for rotation.
  Exit = BI->getSuccessor(0);
  NewHeader = BI->getSuccessor(1);
  if (L->contains(Exit))
    std::swap(Exit, NewHeader);
  assert (NewHeader && "Unable to determine new loop header");
  assert(L->contains(NewHeader) && !L->contains(Exit) &&
         "Unable to determine loop header and exit blocks");

  // Check size of original header and reject
  // loop if it is very big.
  if (OrigHeader->getInstList().size() > MAX_HEADER_SIZE)
    return false;

  // Now, this loop is suitable for rotation.

  // Copy PHI nodes and other instructions from original header
  // into new pre-header. Unlike original header, new pre-header is
  // not a member of loop. New pre-header has only one predecessor,
  // that is original loop pre-header.
  //
  // New loop header is one and only successor of original header that
  // is inside the loop. All other original header successors are outside
  // the loop. Copy PHI Nodes from original header into new loop header.
  // Add second incoming value, from new loop pre-header into these phi
  // nodes. If a value defined in original header is used outside original
  // header then new loop header will need new phi nodes with two incoming
  // values, one definition from original header and second definition is
  // from new loop pre-header (which is a clone of original header definition).

  NewPreHeader = new BasicBlock("bb.nph", OrigHeader->getParent(), OrigHeader);
  BasicBlock::iterator I = OrigHeader->begin(), E = OrigHeader->end();
  for (; I != E; ++I) {
    Instruction *In = I;

    PHINode *PN = dyn_cast<PHINode>(I);
    if (!PN)
      break;

    // Create new PHI node with one value incoming from OrigPreHeader.
    // NewPreHeader has only one predecessor, OrigPreHeader.
    PHINode *NPH = new PHINode(In->getType(), In->getName());
    NPH->addIncoming(PN->getIncomingValueForBlock(OrigPreHeader),
                     OrigPreHeader);
    NewPreHeader->getInstList().push_back(NPH);

    // Create new PHI node with two incoming values for NewHeader.
    // One incoming value is from OrigLatch (through OrigHeader) and
    // second incoming value is from NewPreHeader.
    PHINode *NH = new PHINode(In->getType(), In->getName());
    NH->addIncoming(PN->getIncomingValueForBlock(OrigLatch), OrigHeader);
    NH->addIncoming(NPH, NewPreHeader);
    NewHeader->getInstList().push_front(NH);

    // "In" can be replaced by NPH or NH at various places.
    LoopHeaderInfo.push_back(RenameData(In, NPH, NH));
  }

  // Now, handle non-phi instructions.
  for (; I != E; ++I) {
    Instruction *In = I;

    assert (!isa<PHINode>(In) && "PHINode is not expected here");
    // This is not a PHI instruction. Insert its clone into NewPreHeader.
    // If this instruction is using a value from same basic block then
    // update it to use value from cloned instruction.
    Instruction *C = In->clone();
    C->setName(In->getName());
    NewPreHeader->getInstList().push_back(C);

    // If this instruction is used outside this basic block then
    // create new PHINode for this instruction.
    Instruction *NewHeaderReplacement = NULL;
    if (usedOutsideOriginalHeader(In)) {
      PHINode *PN = new PHINode(In->getType(), In->getName());
      PN->addIncoming(In, OrigHeader);
      PN->addIncoming(C, NewPreHeader);
      NewHeader->getInstList().push_front(PN);
      NewHeaderReplacement = PN;
    }

    // "In" can be replaced by NPH or NH at various places.
    LoopHeaderInfo.push_back(RenameData(In, C, NewHeaderReplacement));
  }

  // Update new pre-header.
  // Rename values that are defined in original header to reflects values
  // defined in new pre-header.
  for (SmallVector<RenameData, MAX_HEADER_SIZE>::iterator
         I = LoopHeaderInfo.begin(), E = LoopHeaderInfo.end(); I != E; ++I) {

    const RenameData &ILoopHeaderInfo = *I;
    Instruction *In = ILoopHeaderInfo.Original;
    Instruction *C = ILoopHeaderInfo.PreHeader;

    // If this instruction is not from new pre-header then is not new
    // pre-header then this instruction is not handled here.
    if (C->getParent() != NewPreHeader)
      continue;

    // PHINodes uses value from pre-header predecessors.
    if (isa<PHINode>(In))
      continue;

    for (unsigned opi = 0, e = In->getNumOperands(); opi != e; ++opi) {
      if (Instruction *OpPhi = dyn_cast<PHINode>(In->getOperand(opi))) {
        if (RenameData *D = findReplacementData(OpPhi))
          C->setOperand(opi, D->PreHeader);
      }
      else if (Instruction *OpInsn =
               dyn_cast<Instruction>(In->getOperand(opi))) {
        if (RenameData *D = findReplacementData(OpInsn))
          C->setOperand(opi, D->PreHeader);
      }
    }
  }

  // Rename uses of original header instructions to reflect their new
  // definitions (either from new pre-header node or from newly created
  // new header PHINodes.
  //
  // Original header instructions are used in
  // 1) Original header:
  //
  //    If instruction is used in non-phi instructions then it is using
  //    defintion from original heder iteself. Do not replace this use
  //    with definition from new header or new pre-header.
  //
  //    If instruction is used in phi node then it is an incoming
  //    value. Rename its use to reflect new definition from new-preheader
  //    or new header.
  //
  // 2) Inside loop but not in original header
  //
  //    Replace this use to reflect definition from new header.
  for (SmallVector<RenameData, MAX_HEADER_SIZE>::iterator
         I = LoopHeaderInfo.begin(), E = LoopHeaderInfo.end(); I != E; ++I) {

    const RenameData &ILoopHeaderInfo = *I;
    if (!ILoopHeaderInfo.Header)
      continue;

    Instruction *OldPhi = ILoopHeaderInfo.Original;
    Instruction *NewPhi = ILoopHeaderInfo.Header;

    // Before replacing uses, collect them first, so that iterator is
    // not invalidated.
    SmallVector<Instruction *, 16> AllUses;
    for (Value::use_iterator UI = OldPhi->use_begin(), UE = OldPhi->use_end();
         UI != UE; ++UI) {
      Instruction *U = cast<Instruction>(UI);
      AllUses.push_back(U);
    }

    for (SmallVector<Instruction *, 16>::iterator UI = AllUses.begin(),
           UE = AllUses.end(); UI != UE; ++UI) {
      Instruction *U = *UI;
      BasicBlock *Parent = U->getParent();

      // Used inside original header
      if (Parent == OrigHeader) {
        // Do not rename uses inside original header non-phi instructions.
        PHINode *PU = dyn_cast<PHINode>(U);
        if (!PU)
          continue;

        // Do not rename uses inside original header phi nodes, if the
        // incoming value is for new header.
        if (PU->getBasicBlockIndex(NewHeader) != -1
            && PU->getIncomingValueForBlock(NewHeader) == U)
          continue;

       U->replaceUsesOfWith(OldPhi, NewPhi);
       continue;
      }

      // Used inside loop, but not in original header.
      if (L->contains(U->getParent())) {
        if (U != NewPhi)
          U->replaceUsesOfWith(OldPhi, NewPhi);
        continue;
      }

      // Used inside Exit Block. Since we are in LCSSA form, U must be PHINode.
      assert (U->getParent() == Exit
              && "Need to propagate new PHI into Exit blocks");
      assert (isa<PHINode>(U) && "Use in Exit Block that is not PHINode");

      PHINode *UPhi = cast<PHINode>(U);

      // UPhi already has one incoming argument from original header.
      // Add second incoming argument from new Pre header.

      UPhi->addIncoming(ILoopHeaderInfo.PreHeader, NewPreHeader);
    }
  }

  /// Make sure all Exit block PHINodes have required incoming values.
  updateExitBlock();

  // Update CFG

  // Removing incoming branch from loop preheader to original header.
  // Now original header is inside the loop.
  OrigHeader->removePredecessor(OrigPreHeader);

  // Establish NewPreHeader as loop preheader. Add unconditional branch
  // from original loop pre-header to new loop pre-header. Add NewPreHEader
  // in loop nest.
  BranchInst *PH_BI = cast<BranchInst>(OrigPreHeader->getTerminator());
  PH_BI->setSuccessor(0, NewPreHeader);
  LoopInfo &LI = LPM.getAnalysis<LoopInfo>();
  if (Loop *PL = LI.getLoopFor(OrigPreHeader))
    PL->addBasicBlockToLoop(NewPreHeader, LI);

  // Make NewHeader as the new header for the loop.
  L->moveToHeader(NewHeader);

  NumRotated++;
  return true;
}

/// Make sure all Exit block PHINodes have required incoming values.
/// If incoming value is constant or defined outside the loop then
/// PHINode may not have an entry for new pre-header.
void LoopRotate::updateExitBlock() {

  for (BasicBlock::iterator I = Exit->begin(), E = Exit->end();
       I != E; ++I) {

    PHINode *PN = dyn_cast<PHINode>(I);
    if (!PN)
      break;

    if (PN->getBasicBlockIndex(NewPreHeader) == -1) {
      Value *V = PN->getIncomingValueForBlock(OrigHeader);
      if (isa<Constant>(V))
        PN->addIncoming(V, NewPreHeader);
      else {
        RenameData *ILoopHeaderInfo = findReplacementData(cast<Instruction>(V));
        assert (ILoopHeaderInfo && ILoopHeaderInfo->PreHeader && "Missing New Preheader Instruction");
        PN->addIncoming(ILoopHeaderInfo->PreHeader, NewPreHeader);
      }
    }
  }
}

/// Initialize local data
void LoopRotate::initialize() {
  L = NULL;
  OrigHeader = NULL;
  OrigPreHeader = NULL;
  NewHeader = NULL;
  NewPreHeader = NULL;
  Exit = NULL;

  LoopHeaderInfo.clear();
}

/// Return true if this instruction is used by any instructions in the loop that
/// aren't in original header.
bool LoopRotate::usedOutsideOriginalHeader(Instruction *In) {

  for (Value::use_iterator UI = In->use_begin(), UE = In->use_end();
       UI != UE; ++UI) {
    Instruction *U = cast<Instruction>(UI);
    if (U->getParent() != OrigHeader) {
      if (L->contains(U->getParent()))
        return true;
    }
  }

  return false;
}

/// Find Replacement information for instruction. Return NULL if it is
/// not available.
RenameData *LoopRotate::findReplacementData(Instruction *In) {

  // Since LoopHeaderInfo is small, linear walk is OK.
  for (SmallVector<RenameData, MAX_HEADER_SIZE>::iterator
         I = LoopHeaderInfo.begin(), E = LoopHeaderInfo.end(); I != E; ++I)
    if (I->Original == In)
      return &(*I);

  return NULL;
}
<|endoftext|>