[llvm] r188890 - MC CFG: Add YAML MCModule representation to enable MC CFG testing.

Ahmed Bougacha ahmed.bougacha at gmail.com
Wed Aug 21 12:47:29 PDT 2013


On Wed, Aug 21, 2013 at 10:32 AM, David Blaikie <dblaikie at gmail.com> wrote:
> On Wed, Aug 21, 2013 at 12:29 AM, Ahmed Bougacha
> <ahmed.bougacha at gmail.com> wrote:
>> Author: ab
>> Date: Wed Aug 21 02:29:02 2013
>> New Revision: 188890
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=188890&view=rev
>> Log:
>> MC CFG: Add YAML MCModule representation to enable MC CFG testing.
>
> Obviously this is for testing future work - but I assume it could be
> used to test existing work that was under tested due to the lack of
> infrastructure? Providing at least an example or two of test coverage
> would be nice to go with such a feature/commit.

I pushed it earlier this morning as r188904.

-- Ahmed

>
>>
>> Like yaml ObjectFiles, this will be very useful for testing the MC CFG
>> implementation (mostly MCObjectDisassembler), by matching the output
>> with YAML, and for potential users of the MC CFG, by using it as an input.
>>
>> There isn't much to the actual format, it is just a serialization of the
>> MCModule class. Of note:
>>   - Basic block references (pred/succ, ..) are represented by the BB's
>>     start address.
>>   - Just as in the MC CFG, instructions are MCInsts with a size.
>>   - Operands have a prefix representing the type (only register and
>>     immediate supported here).
>>   - Instruction opcodes are represented by their names; enum values aren't
>>     stable, enum names mostly are: usually, a change to a name would need
>>     lots of changes in the backend anyway.
>>     Same with registers.
>>
>> All in all, an example is better than 1000 words, here goes:
>>
>> A simple binary:
>>
>>   Disassembly of section __TEXT,__text:
>>   _main:
>>   100000f9c:      48 8b 46 08             movq    8(%rsi), %rax
>>   100000fa0:      0f be 00                movsbl  (%rax), %eax
>>   100000fa3:      3b 04 25 48 00 00 00    cmpl    72, %eax
>>   100000faa:      0f 8c 07 00 00 00       jl      7 <.Lend>
>>   100000fb0:      2b 04 25 48 00 00 00    subl    72, %eax
>>   .Lend:
>>   100000fb7:      c3                      ret
>>
>> And the (pretty verbose) generated YAML:
>>
>>   ---
>>   Atoms:
>>     - StartAddress:    0x0000000100000F9C
>>       Size:            20
>>       Type:            Text
>>       Content:
>>         - Inst:            MOV64rm
>>           Size:            4
>>           Ops:             [ RRAX, RRSI, I1, R, I8, R ]
>>         - Inst:            MOVSX32rm8
>>           Size:            3
>>           Ops:             [ REAX, RRAX, I1, R, I0, R ]
>>         - Inst:            CMP32rm
>>           Size:            7
>>           Ops:             [ REAX, R, I1, R, I72, R ]
>>         - Inst:            JL_4
>>           Size:            6
>>           Ops:             [ I7 ]
>>     - StartAddress:    0x0000000100000FB0
>>       Size:            7
>>       Type:            Text
>>       Content:
>>         - Inst:            SUB32rm
>>           Size:            7
>>           Ops:             [ REAX, REAX, R, I1, R, I72, R ]
>>     - StartAddress:    0x0000000100000FB7
>>       Size:            1
>>       Type:            Text
>>       Content:
>>         - Inst:            RET
>>           Size:            1
>>           Ops:             [  ]
>>   Functions:
>>     - Name:            __text
>>       BasicBlocks:
>>         - Address:         0x0000000100000F9C
>>           Preds:           [  ]
>>           Succs:           [ 0x0000000100000FB7, 0x0000000100000FB0 ]
>>      <snip>
>>   ...
>>
>> Added:
>>     llvm/trunk/include/llvm/MC/MCModuleYAML.h
>>     llvm/trunk/lib/MC/MCModuleYAML.cpp
>> Modified:
>>     llvm/trunk/lib/MC/CMakeLists.txt
>>     llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp
>>
>> Added: llvm/trunk/include/llvm/MC/MCModuleYAML.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCModuleYAML.h?rev=188890&view=auto
>> ==============================================================================
>> --- llvm/trunk/include/llvm/MC/MCModuleYAML.h (added)
>> +++ llvm/trunk/include/llvm/MC/MCModuleYAML.h Wed Aug 21 02:29:02 2013
>> @@ -0,0 +1,41 @@
>> +//===- MCModuleYAML.h - MCModule YAMLIO implementation ----------*- C++ -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +///
>> +/// \file
>> +/// \brief This file declares classes for handling the YAML representation
>> +/// of MCModule.
>> +///
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_OBJECT_MCMODULEYAML_H
>> +#define LLVM_OBJECT_MCMODULEYAML_H
>> +
>> +#include "llvm/ADT/OwningPtr.h"
>> +#include "llvm/ADT/StringRef.h"
>> +#include "llvm/MC/MCModule.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +
>> +namespace llvm {
>> +
>> +class MCInstrInfo;
>> +class MCRegisterInfo;
>> +
>> +/// \brief Dump a YAML representation of the MCModule \p MCM to \p OS.
>> +/// \returns The empty string on success, an error message on failure.
>> +StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM,
>> +                        const MCInstrInfo &MII, const MCRegisterInfo &MRI);
>> +
>> +/// \brief Creates a new module and returns it in \p MCM.
>> +/// \returns The empty string on success, an error message on failure.
>> +StringRef yaml2mcmodule(OwningPtr<MCModule> &MCM, StringRef YamlContent,
>> +                        const MCInstrInfo &MII, const MCRegisterInfo &MRI);
>> +
>> +} // end namespace llvm
>> +
>> +#endif
>>
>> Modified: llvm/trunk/lib/MC/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/CMakeLists.txt?rev=188890&r1=188889&r2=188890&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/MC/CMakeLists.txt (original)
>> +++ llvm/trunk/lib/MC/CMakeLists.txt Wed Aug 21 02:29:02 2013
>> @@ -25,6 +25,7 @@ add_llvm_library(LLVMMC
>>    MCMachOStreamer.cpp
>>    MCMachObjectTargetWriter.cpp
>>    MCModule.cpp
>> +  MCModuleYAML.cpp
>>    MCNullStreamer.cpp
>>    MCObjectFileInfo.cpp
>>    MCObjectDisassembler.cpp
>>
>> Added: llvm/trunk/lib/MC/MCModuleYAML.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCModuleYAML.cpp?rev=188890&view=auto
>> ==============================================================================
>> --- llvm/trunk/lib/MC/MCModuleYAML.cpp (added)
>> +++ llvm/trunk/lib/MC/MCModuleYAML.cpp Wed Aug 21 02:29:02 2013
>> @@ -0,0 +1,461 @@
>> +//===- MCModuleYAML.cpp - MCModule YAMLIO implementation ------------------===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file defines classes for handling the YAML representation of MCModule.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/MC/MCModuleYAML.h"
>> +#include "llvm/ADT/StringMap.h"
>> +#include "llvm/MC/MCAtom.h"
>> +#include "llvm/MC/MCFunction.h"
>> +#include "llvm/MC/MCInstrInfo.h"
>> +#include "llvm/MC/MCRegisterInfo.h"
>> +#include "llvm/Object/YAML.h"
>> +#include "llvm/Support/Allocator.h"
>> +#include "llvm/Support/MathExtras.h"
>> +#include "llvm/Support/YAMLTraits.h"
>> +#include <vector>
>> +
>> +namespace llvm {
>> +
>> +namespace {
>> +
>> +// This class is used to map opcode and register names to enum values.
>> +//
>> +// There are at least 3 obvious ways to do this:
>> +// 1- Generate an MII/MRI method using a tablegen StringMatcher
>> +// 2- Write an MII/MRI method using std::lower_bound and the assumption that
>> +//    the enums are sorted (starting at a fixed value).
>> +// 3- Do the matching manually as is done here.
>> +//
>> +// Why 3?
>> +// 1- A StringMatcher function for thousands of entries would incur
>> +//    a non-negligible binary size overhead.
>> +// 2- The lower_bound comparators would be somewhat involved and aren't
>> +//    obviously reusable (see LessRecordRegister in llvm/TableGen/Record.h)
>> +// 3- This isn't actually something useful outside tests (but the same argument
>> +//    can be made against having {MII,MRI}::getName).
>> +//
>> +// If this becomes useful outside this specific situation, feel free to do
>> +// the Right Thing (tm) and move the functionality to MII/MRI.
>> +//
>> +class InstrRegInfoHolder {
>> +  typedef StringMap<unsigned, BumpPtrAllocator> EnumValByNameTy;
>> +  EnumValByNameTy InstEnumValueByName;
>> +  EnumValByNameTy RegEnumValueByName;
>> +
>> +public:
>> +  const MCInstrInfo &MII;
>> +  const MCRegisterInfo &MRI;
>> +  InstrRegInfoHolder(const MCInstrInfo &MII, const MCRegisterInfo &MRI)
>> +      : InstEnumValueByName(NextPowerOf2(MII.getNumOpcodes())),
>> +        RegEnumValueByName(NextPowerOf2(MRI.getNumRegs())), MII(MII), MRI(MRI) {
>> +    for (int i = 0, e = MII.getNumOpcodes(); i != e; ++i)
>> +      InstEnumValueByName[MII.getName(i)] = i;
>> +    for (int i = 0, e = MRI.getNumRegs(); i != e; ++i)
>> +      RegEnumValueByName[MRI.getName(i)] = i;
>> +  }
>> +
>> +  bool matchRegister(StringRef Name, unsigned &Reg) {
>> +    EnumValByNameTy::const_iterator It = RegEnumValueByName.find(Name);
>> +    if (It == RegEnumValueByName.end())
>> +      return false;
>> +    Reg = It->getValue();
>> +    return true;
>> +  }
>> +  bool matchOpcode(StringRef Name, unsigned &Opc) {
>> +    EnumValByNameTy::const_iterator It = InstEnumValueByName.find(Name);
>> +    if (It == InstEnumValueByName.end())
>> +      return false;
>> +    Opc = It->getValue();
>> +    return true;
>> +  }
>> +};
>> +
>> +} // end unnamed namespace
>> +
>> +namespace MCModuleYAML {
>> +
>> +LLVM_YAML_STRONG_TYPEDEF(unsigned, OpcodeEnum)
>> +
>> +struct Operand {
>> +  MCOperand MCOp;
>> +};
>> +
>> +struct Inst {
>> +  OpcodeEnum Opcode;
>> +  std::vector<Operand> Operands;
>> +  uint64_t Size;
>> +};
>> +
>> +struct Atom {
>> +  MCAtom::AtomKind Type;
>> +  yaml::Hex64 StartAddress;
>> +  uint64_t Size;
>> +
>> +  std::vector<Inst> Insts;
>> +  object::yaml::BinaryRef Data;
>> +};
>> +
>> +struct BasicBlock {
>> +  yaml::Hex64 Address;
>> +  std::vector<yaml::Hex64> Preds;
>> +  std::vector<yaml::Hex64> Succs;
>> +};
>> +
>> +struct Function {
>> +  StringRef Name;
>> +  std::vector<BasicBlock> BasicBlocks;
>> +};
>> +
>> +struct Module {
>> +  std::vector<Atom> Atoms;
>> +  std::vector<Function> Functions;
>> +};
>> +
>> +} // end namespace MCModuleYAML
>> +} // end namespace llvm
>> +
>> +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
>> +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::MCModuleYAML::Operand)
>> +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Inst)
>> +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Atom)
>> +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::BasicBlock)
>> +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Function)
>> +
>> +namespace llvm {
>> +
>> +namespace yaml {
>> +
>> +template <> struct ScalarEnumerationTraits<MCAtom::AtomKind> {
>> +  static void enumeration(IO &IO, MCAtom::AtomKind &Kind);
>> +};
>> +
>> +template <> struct MappingTraits<MCModuleYAML::Atom> {
>> +  static void mapping(IO &IO, MCModuleYAML::Atom &A);
>> +};
>> +
>> +template <> struct MappingTraits<MCModuleYAML::Inst> {
>> +  static void mapping(IO &IO, MCModuleYAML::Inst &I);
>> +};
>> +
>> +template <> struct MappingTraits<MCModuleYAML::BasicBlock> {
>> +  static void mapping(IO &IO, MCModuleYAML::BasicBlock &BB);
>> +};
>> +
>> +template <> struct MappingTraits<MCModuleYAML::Function> {
>> +  static void mapping(IO &IO, MCModuleYAML::Function &Fn);
>> +};
>> +
>> +template <> struct MappingTraits<MCModuleYAML::Module> {
>> +  static void mapping(IO &IO, MCModuleYAML::Module &M);
>> +};
>> +
>> +template <> struct ScalarTraits<MCModuleYAML::Operand> {
>> +  static void output(const MCModuleYAML::Operand &, void *,
>> +                     llvm::raw_ostream &);
>> +  static StringRef input(StringRef, void *, MCModuleYAML::Operand &);
>> +};
>> +
>> +template <> struct ScalarTraits<MCModuleYAML::OpcodeEnum> {
>> +  static void output(const MCModuleYAML::OpcodeEnum &, void *,
>> +                     llvm::raw_ostream &);
>> +  static StringRef input(StringRef, void *, MCModuleYAML::OpcodeEnum &);
>> +};
>> +
>> +void ScalarEnumerationTraits<MCAtom::AtomKind>::enumeration(
>> +    IO &IO, MCAtom::AtomKind &Value) {
>> +  IO.enumCase(Value, "Text", MCAtom::TextAtom);
>> +  IO.enumCase(Value, "Data", MCAtom::DataAtom);
>> +}
>> +
>> +void MappingTraits<MCModuleYAML::Atom>::mapping(IO &IO, MCModuleYAML::Atom &A) {
>> +  IO.mapRequired("StartAddress", A.StartAddress);
>> +  IO.mapRequired("Size", A.Size);
>> +  IO.mapRequired("Type", A.Type);
>> +  if (A.Type == MCAtom::TextAtom)
>> +    IO.mapRequired("Content", A.Insts);
>> +  else if (A.Type == MCAtom::DataAtom)
>> +    IO.mapRequired("Content", A.Data);
>> +}
>> +
>> +void MappingTraits<MCModuleYAML::Inst>::mapping(IO &IO, MCModuleYAML::Inst &I) {
>> +  IO.mapRequired("Inst", I.Opcode);
>> +  IO.mapRequired("Size", I.Size);
>> +  IO.mapRequired("Ops", I.Operands);
>> +}
>> +
>> +void
>> +MappingTraits<MCModuleYAML::BasicBlock>::mapping(IO &IO,
>> +                                                 MCModuleYAML::BasicBlock &BB) {
>> +  IO.mapRequired("Address", BB.Address);
>> +  IO.mapRequired("Preds", BB.Preds);
>> +  IO.mapRequired("Succs", BB.Succs);
>> +}
>> +
>> +void MappingTraits<MCModuleYAML::Function>::mapping(IO &IO,
>> +                                                    MCModuleYAML::Function &F) {
>> +  IO.mapRequired("Name", F.Name);
>> +  IO.mapRequired("BasicBlocks", F.BasicBlocks);
>> +}
>> +
>> +void MappingTraits<MCModuleYAML::Module>::mapping(IO &IO,
>> +                                                  MCModuleYAML::Module &M) {
>> +  IO.mapRequired("Atoms", M.Atoms);
>> +  IO.mapOptional("Functions", M.Functions);
>> +}
>> +
>> +void
>> +ScalarTraits<MCModuleYAML::Operand>::output(const MCModuleYAML::Operand &Val,
>> +                                            void *Ctx, raw_ostream &Out) {
>> +  InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
>> +
>> +  // FIXME: Doesn't support FPImm and expr/inst, but do these make sense?
>> +  if (Val.MCOp.isImm())
>> +    Out << "I" << Val.MCOp.getImm();
>> +  else if (Val.MCOp.isReg())
>> +    Out << "R" << IRI->MRI.getName(Val.MCOp.getReg());
>> +  else
>> +    llvm_unreachable("Trying to output invalid MCOperand!");
>> +}
>> +
>> +StringRef
>> +ScalarTraits<MCModuleYAML::Operand>::input(StringRef Scalar, void *Ctx,
>> +                                           MCModuleYAML::Operand &Val) {
>> +  InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
>> +  char Type = 0;
>> +  if (Scalar.size() >= 1)
>> +    Type = Scalar.front();
>> +  if (Type != 'R' && Type != 'I')
>> +    return "Operand must start with 'R' (register) or 'I' (immediate).";
>> +  if (Type == 'R') {
>> +    unsigned Reg;
>> +    if (!IRI->matchRegister(Scalar.substr(1), Reg))
>> +      return "Invalid register name.";
>> +    Val.MCOp = MCOperand::CreateReg(Reg);
>> +  } else if (Type == 'I') {
>> +    int64_t RIVal;
>> +    if (Scalar.substr(1).getAsInteger(10, RIVal))
>> +      return "Invalid immediate value.";
>> +    Val.MCOp = MCOperand::CreateImm(RIVal);
>> +  } else {
>> +    Val.MCOp = MCOperand();
>> +  }
>> +  return StringRef();
>> +}
>> +
>> +void ScalarTraits<MCModuleYAML::OpcodeEnum>::output(
>> +    const MCModuleYAML::OpcodeEnum &Val, void *Ctx, raw_ostream &Out) {
>> +  InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
>> +  Out << IRI->MII.getName(Val);
>> +}
>> +
>> +StringRef
>> +ScalarTraits<MCModuleYAML::OpcodeEnum>::input(StringRef Scalar, void *Ctx,
>> +                                              MCModuleYAML::OpcodeEnum &Val) {
>> +  InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
>> +  unsigned Opc;
>> +  if (!IRI->matchOpcode(Scalar, Opc))
>> +    return "Invalid instruction opcode.";
>> +  Val = Opc;
>> +  return "";
>> +}
>> +
>> +} // end namespace yaml
>> +
>> +namespace {
>> +
>> +class MCModule2YAML {
>> +  const MCModule &MCM;
>> +  MCModuleYAML::Module YAMLModule;
>> +  void dumpAtom(const MCAtom *MCA);
>> +  void dumpFunction(const MCFunction *MCF);
>> +  void dumpBasicBlock(const MCBasicBlock *MCBB);
>> +
>> +public:
>> +  MCModule2YAML(const MCModule &MCM);
>> +  MCModuleYAML::Module &getYAMLModule();
>> +};
>> +
>> +class YAML2MCModule {
>> +  MCModule &MCM;
>> +
>> +public:
>> +  YAML2MCModule(MCModule &MCM);
>> +  StringRef parse(const MCModuleYAML::Module &YAMLModule);
>> +};
>> +
>> +} // end unnamed namespace
>> +
>> +MCModule2YAML::MCModule2YAML(const MCModule &MCM) : MCM(MCM), YAMLModule() {
>> +  for (MCModule::const_atom_iterator AI = MCM.atom_begin(), AE = MCM.atom_end();
>> +       AI != AE; ++AI)
>> +    dumpAtom(*AI);
>> +  for (MCModule::const_func_iterator FI = MCM.func_begin(), FE = MCM.func_end();
>> +       FI != FE; ++FI)
>> +    dumpFunction(*FI);
>> +}
>> +
>> +void MCModule2YAML::dumpAtom(const MCAtom *MCA) {
>> +  YAMLModule.Atoms.resize(YAMLModule.Atoms.size() + 1);
>> +  MCModuleYAML::Atom &A = YAMLModule.Atoms.back();
>> +  A.Type = MCA->getKind();
>> +  A.StartAddress = MCA->getBeginAddr();
>> +  A.Size = MCA->getEndAddr() - MCA->getBeginAddr() + 1;
>> +  if (const MCTextAtom *TA = dyn_cast<MCTextAtom>(MCA)) {
>> +    const size_t InstCount = TA->size();
>> +    A.Insts.resize(InstCount);
>> +    for (size_t i = 0; i != InstCount; ++i) {
>> +      const MCDecodedInst &MCDI = TA->at(i);
>> +      A.Insts[i].Opcode = MCDI.Inst.getOpcode();
>> +      A.Insts[i].Size = MCDI.Size;
>> +      const unsigned OpCount = MCDI.Inst.getNumOperands();
>> +      A.Insts[i].Operands.resize(OpCount);
>> +      for (unsigned oi = 0; oi != OpCount; ++oi)
>> +        A.Insts[i].Operands[oi].MCOp = MCDI.Inst.getOperand(oi);
>> +    }
>> +  } else if (const MCDataAtom *DA = dyn_cast<MCDataAtom>(MCA)) {
>> +    A.Data = DA->getData();
>> +  } else {
>> +    llvm_unreachable("Unknown atom type.");
>> +  }
>> +}
>> +
>> +void MCModule2YAML::dumpFunction(const MCFunction *MCF) {
>> +  YAMLModule.Functions.resize(YAMLModule.Functions.size() + 1);
>> +  MCModuleYAML::Function &F = YAMLModule.Functions.back();
>> +  F.Name = MCF->getName();
>> +  for (MCFunction::const_iterator BBI = MCF->begin(), BBE = MCF->end();
>> +       BBI != BBE; ++BBI) {
>> +    const MCBasicBlock *MCBB = *BBI;
>> +    F.BasicBlocks.resize(F.BasicBlocks.size() + 1);
>> +    MCModuleYAML::BasicBlock &BB = F.BasicBlocks.back();
>> +    BB.Address = MCBB->getInsts()->getBeginAddr();
>> +    for (MCBasicBlock::pred_const_iterator PI = MCBB->pred_begin(),
>> +                                           PE = MCBB->pred_end();
>> +         PI != PE; ++PI)
>> +      BB.Preds.push_back((*PI)->getInsts()->getBeginAddr());
>> +    for (MCBasicBlock::succ_const_iterator SI = MCBB->succ_begin(),
>> +                                           SE = MCBB->succ_end();
>> +         SI != SE; ++SI)
>> +      BB.Succs.push_back((*SI)->getInsts()->getBeginAddr());
>> +  }
>> +}
>> +
>> +MCModuleYAML::Module &MCModule2YAML::getYAMLModule() { return YAMLModule; }
>> +
>> +YAML2MCModule::YAML2MCModule(MCModule &MCM) : MCM(MCM) {}
>> +
>> +StringRef YAML2MCModule::parse(const MCModuleYAML::Module &YAMLModule) {
>> +  typedef std::vector<MCModuleYAML::Atom>::const_iterator AtomIt;
>> +  typedef std::vector<MCModuleYAML::Inst>::const_iterator InstIt;
>> +  typedef std::vector<MCModuleYAML::Operand>::const_iterator OpIt;
>> +
>> +  typedef DenseMap<uint64_t, MCTextAtom *> AddrToTextAtomTy;
>> +  AddrToTextAtomTy TAByAddr;
>> +
>> +  for (AtomIt AI = YAMLModule.Atoms.begin(), AE = YAMLModule.Atoms.end();
>> +       AI != AE; ++AI) {
>> +    uint64_t StartAddress = AI->StartAddress;
>> +    if (AI->Size == 0)
>> +      return "Atoms can't be empty!";
>> +    uint64_t EndAddress = StartAddress + AI->Size - 1;
>> +    switch (AI->Type) {
>> +    case MCAtom::TextAtom: {
>> +      MCTextAtom *TA = MCM.createTextAtom(StartAddress, EndAddress);
>> +      TAByAddr[StartAddress] = TA;
>> +      for (InstIt II = AI->Insts.begin(), IE = AI->Insts.end(); II != IE;
>> +           ++II) {
>> +        MCInst MI;
>> +        MI.setOpcode(II->Opcode);
>> +        for (OpIt OI = II->Operands.begin(), OE = II->Operands.end(); OI != OE;
>> +             ++OI)
>> +          MI.addOperand(OI->MCOp);
>> +        TA->addInst(MI, II->Size);
>> +      }
>> +      break;
>> +    }
>> +    case MCAtom::DataAtom: {
>> +      MCDataAtom *DA = MCM.createDataAtom(StartAddress, EndAddress);
>> +      SmallVector<char, 64> Data;
>> +      raw_svector_ostream OS(Data);
>> +      AI->Data.writeAsBinary(OS);
>> +      OS.flush();
>> +      for (size_t i = 0, e = Data.size(); i != e; ++i)
>> +        DA->addData((uint8_t)Data[i]);
>> +      break;
>> +    }
>> +    }
>> +  }
>> +
>> +  typedef std::vector<MCModuleYAML::Function>::const_iterator FuncIt;
>> +  typedef std::vector<MCModuleYAML::BasicBlock>::const_iterator BBIt;
>> +  typedef std::vector<yaml::Hex64>::const_iterator AddrIt;
>> +  for (FuncIt FI = YAMLModule.Functions.begin(),
>> +              FE = YAMLModule.Functions.end();
>> +       FI != FE; ++FI) {
>> +    MCFunction *MCFN = MCM.createFunction(FI->Name);
>> +    for (BBIt BBI = FI->BasicBlocks.begin(), BBE = FI->BasicBlocks.end();
>> +         BBI != BBE; ++BBI) {
>> +      AddrToTextAtomTy::const_iterator It = TAByAddr.find(BBI->Address);
>> +      if (It == TAByAddr.end())
>> +        return "Basic block start address doesn't match any text atom!";
>> +      MCFN->createBlock(*It->second);
>> +    }
>> +    for (BBIt BBI = FI->BasicBlocks.begin(), BBE = FI->BasicBlocks.end();
>> +         BBI != BBE; ++BBI) {
>> +      MCBasicBlock *MCBB = MCFN->find(BBI->Address);
>> +      if (!MCBB)
>> +        return "Couldn't find matching basic block in function.";
>> +      for (AddrIt PI = BBI->Preds.begin(), PE = BBI->Preds.end(); PI != PE;
>> +           ++PI) {
>> +        MCBasicBlock *Pred = MCFN->find(*PI);
>> +        if (!Pred)
>> +          return "Couldn't find predecessor basic block.";
>> +        MCBB->addPredecessor(Pred);
>> +      }
>> +      for (AddrIt SI = BBI->Succs.begin(), SE = BBI->Succs.end(); SI != SE;
>> +           ++SI) {
>> +        MCBasicBlock *Succ = MCFN->find(*SI);
>> +        if (!Succ)
>> +          return "Couldn't find predecessor basic block.";
>> +        MCBB->addSuccessor(Succ);
>> +      }
>> +    }
>> +  }
>> +  return "";
>> +}
>> +
>> +StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM,
>> +                        const MCInstrInfo &MII, const MCRegisterInfo &MRI) {
>> +  MCModule2YAML Dumper(MCM);
>> +  InstrRegInfoHolder IRI(MII, MRI);
>> +  yaml::Output YOut(OS, (void *)&IRI);
>> +  YOut << Dumper.getYAMLModule();
>> +  return "";
>> +}
>> +
>> +StringRef yaml2mcmodule(OwningPtr<MCModule> &MCM, StringRef YamlContent,
>> +                        const MCInstrInfo &MII, const MCRegisterInfo &MRI) {
>> +  MCM.reset(new MCModule);
>> +  YAML2MCModule Parser(*MCM);
>> +  MCModuleYAML::Module YAMLModule;
>> +  InstrRegInfoHolder IRI(MII, MRI);
>> +  yaml::Input YIn(YamlContent, (void *)&IRI);
>> +  YIn >> YAMLModule;
>> +  if (error_code ec = YIn.error())
>> +    return ec.message();
>> +  StringRef err = Parser.parse(YAMLModule);
>> +  if (!err.empty())
>> +    return err;
>> +  return "";
>> +}
>> +
>> +} // end namespace llvm
>>
>> Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp?rev=188890&r1=188889&r2=188890&view=diff
>> ==============================================================================
>> --- llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp (original)
>> +++ llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Wed Aug 21 02:29:02 2013
>> @@ -31,6 +31,7 @@
>>  #include "llvm/MC/MCInstrAnalysis.h"
>>  #include "llvm/MC/MCInstrInfo.h"
>>  #include "llvm/MC/MCModule.h"
>> +#include "llvm/MC/MCModuleYAML.h"
>>  #include "llvm/MC/MCObjectDisassembler.h"
>>  #include "llvm/MC/MCObjectFileInfo.h"
>>  #include "llvm/MC/MCObjectSymbolizer.h"
>> @@ -61,6 +62,7 @@
>>  #include <algorithm>
>>  #include <cctype>
>>  #include <cstring>
>> +
>>  using namespace llvm;
>>  using namespace object;
>>
>> @@ -139,6 +141,12 @@ static cl::opt<bool>
>>  CFG("cfg", cl::desc("Create a CFG for every function found in the object"
>>                        " and write it to a graphviz file"));
>>
>> +// FIXME: Does it make sense to have a dedicated tool for yaml cfg output?
>> +static cl::opt<std::string>
>> +YAMLCFG("yaml-cfg",
>> +        cl::desc("Create a CFG and write it as a YAML MCModule."),
>> +        cl::value_desc("yaml output file"));
>> +
>>  static StringRef ToolName;
>>
>>  bool llvm::error(error_code ec) {
>> @@ -178,6 +186,7 @@ static const Target *getTarget(const Obj
>>  }
>>
>>  // Write a graphviz file for the CFG inside an MCFunction.
>> +// FIXME: Use GraphWriter
>>  static void emitDOTFile(const char *FileName, const MCFunction &f,
>>                          MCInstPrinter *IP) {
>>    // Start a new dot file.
>> @@ -333,7 +342,7 @@ static void DisassembleObject(const Obje
>>      return;
>>    }
>>
>> -  if (CFG) {
>> +  if (CFG || !YAMLCFG.empty()) {
>>      OwningPtr<MCObjectDisassembler> OD(
>>        new MCObjectDisassembler(*Obj, *DisAsm, *MIA));
>>      OwningPtr<MCModule> Mod(OD->buildModule(/* withCFG */ true));
>> @@ -350,14 +359,25 @@ static void DisassembleObject(const Obje
>>          }
>>        }
>>      }
>> -    for (MCModule::const_func_iterator FI = Mod->func_begin(),
>> -                                       FE = Mod->func_end();
>> -                                       FI != FE; ++FI) {
>> -      static int filenum = 0;
>> -      emitDOTFile((Twine((*FI)->getName()) + "_" +
>> -                   utostr(filenum) + ".dot").str().c_str(),
>> -                    **FI, IP.get());
>> -      ++filenum;
>> +    if (CFG) {
>> +      for (MCModule::const_func_iterator FI = Mod->func_begin(),
>> +                                         FE = Mod->func_end();
>> +                                         FI != FE; ++FI) {
>> +        static int filenum = 0;
>> +        emitDOTFile((Twine((*FI)->getName()) + "_" +
>> +                     utostr(filenum) + ".dot").str().c_str(),
>> +                      **FI, IP.get());
>> +        ++filenum;
>> +      }
>> +    }
>> +    if (!YAMLCFG.empty()) {
>> +      std::string Error;
>> +      raw_fd_ostream YAMLOut(YAMLCFG.c_str(), Error);
>> +      if (!Error.empty()) {
>> +        errs() << "llvm-objdump: warning: " << Error << '\n';
>> +        return;
>> +      }
>> +      mcmodule2yaml(YAMLOut, *Mod, *MII, *MRI);
>>      }
>>    }
>>
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list