LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MCModuleYAML.cpp
Go to the documentation of this file.
1 //===- MCModuleYAML.cpp - MCModule YAMLIO implementation ------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines classes for handling the YAML representation of MCModule.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/MC/MCModuleYAML.h"
15 #include "llvm/ADT/StringMap.h"
16 #include "llvm/MC/MCAtom.h"
17 #include "llvm/MC/MCFunction.h"
18 #include "llvm/MC/MCInstrInfo.h"
19 #include "llvm/MC/MCRegisterInfo.h"
20 #include "llvm/Object/YAML.h"
21 #include "llvm/Support/Allocator.h"
24 #include <vector>
25 
26 namespace llvm {
27 
28 namespace {
29 
30 // This class is used to map opcode and register names to enum values.
31 //
32 // There are at least 3 obvious ways to do this:
33 // 1- Generate an MII/MRI method using a tablegen StringMatcher
34 // 2- Write an MII/MRI method using std::lower_bound and the assumption that
35 // the enums are sorted (starting at a fixed value).
36 // 3- Do the matching manually as is done here.
37 //
38 // Why 3?
39 // 1- A StringMatcher function for thousands of entries would incur
40 // a non-negligible binary size overhead.
41 // 2- The lower_bound comparators would be somewhat involved and aren't
42 // obviously reusable (see LessRecordRegister in llvm/TableGen/Record.h)
43 // 3- This isn't actually something useful outside tests (but the same argument
44 // can be made against having {MII,MRI}::getName).
45 //
46 // If this becomes useful outside this specific situation, feel free to do
47 // the Right Thing (tm) and move the functionality to MII/MRI.
48 //
49 class InstrRegInfoHolder {
50  typedef StringMap<unsigned, BumpPtrAllocator> EnumValByNameTy;
51  EnumValByNameTy InstEnumValueByName;
52  EnumValByNameTy RegEnumValueByName;
53 
54 public:
55  const MCInstrInfo &MII;
56  const MCRegisterInfo &MRI;
57  InstrRegInfoHolder(const MCInstrInfo &MII, const MCRegisterInfo &MRI)
58  : InstEnumValueByName(NextPowerOf2(MII.getNumOpcodes())),
59  RegEnumValueByName(NextPowerOf2(MRI.getNumRegs())), MII(MII), MRI(MRI) {
60  for (int i = 0, e = MII.getNumOpcodes(); i != e; ++i)
61  InstEnumValueByName[MII.getName(i)] = i;
62  for (int i = 0, e = MRI.getNumRegs(); i != e; ++i)
63  RegEnumValueByName[MRI.getName(i)] = i;
64  }
65 
66  bool matchRegister(StringRef Name, unsigned &Reg) {
68  if (It == RegEnumValueByName.end())
69  return false;
70  Reg = It->getValue();
71  return true;
72  }
73  bool matchOpcode(StringRef Name, unsigned &Opc) {
75  if (It == InstEnumValueByName.end())
76  return false;
77  Opc = It->getValue();
78  return true;
79  }
80 };
81 
82 } // end unnamed namespace
83 
84 namespace MCModuleYAML {
85 
86 LLVM_YAML_STRONG_TYPEDEF(unsigned, OpcodeEnum)
87 
88 struct Operand {
90 };
91 
92 struct Inst {
93  OpcodeEnum Opcode;
94  std::vector<Operand> Operands;
95  uint64_t Size;
96 };
97 
98 struct Atom {
100  yaml::Hex64 StartAddress;
101  uint64_t Size;
102 
103  std::vector<Inst> Insts;
105 };
106 
107 struct BasicBlock {
108  yaml::Hex64 Address;
109  std::vector<yaml::Hex64> Preds;
110  std::vector<yaml::Hex64> Succs;
111 };
112 
113 struct Function {
115  std::vector<BasicBlock> BasicBlocks;
116 };
117 
118 struct Module {
119  std::vector<Atom> Atoms;
120  std::vector<Function> Functions;
121 };
122 
123 } // end namespace MCModuleYAML
124 } // end namespace llvm
125 
126 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
127 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::MCModuleYAML::Operand)
128 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Inst)
129 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Atom)
130 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::BasicBlock)
131 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Function)
132 
133 namespace llvm {
134 
135 namespace yaml {
136 
137 template <> struct ScalarEnumerationTraits<MCAtom::AtomKind> {
138  static void enumeration(IO &IO, MCAtom::AtomKind &Kind);
139 };
140 
141 template <> struct MappingTraits<MCModuleYAML::Atom> {
142  static void mapping(IO &IO, MCModuleYAML::Atom &A);
143 };
144 
145 template <> struct MappingTraits<MCModuleYAML::Inst> {
146  static void mapping(IO &IO, MCModuleYAML::Inst &I);
147 };
148 
149 template <> struct MappingTraits<MCModuleYAML::BasicBlock> {
150  static void mapping(IO &IO, MCModuleYAML::BasicBlock &BB);
151 };
152 
153 template <> struct MappingTraits<MCModuleYAML::Function> {
154  static void mapping(IO &IO, MCModuleYAML::Function &Fn);
155 };
156 
157 template <> struct MappingTraits<MCModuleYAML::Module> {
158  static void mapping(IO &IO, MCModuleYAML::Module &M);
159 };
160 
161 template <> struct ScalarTraits<MCModuleYAML::Operand> {
162  static void output(const MCModuleYAML::Operand &, void *,
164  static StringRef input(StringRef, void *, MCModuleYAML::Operand &);
165 };
166 
167 template <> struct ScalarTraits<MCModuleYAML::OpcodeEnum> {
168  static void output(const MCModuleYAML::OpcodeEnum &, void *,
170  static StringRef input(StringRef, void *, MCModuleYAML::OpcodeEnum &);
171 };
172 
175  IO.enumCase(Value, "Text", MCAtom::TextAtom);
176  IO.enumCase(Value, "Data", MCAtom::DataAtom);
177 }
178 
180  IO.mapRequired("StartAddress", A.StartAddress);
181  IO.mapRequired("Size", A.Size);
182  IO.mapRequired("Type", A.Type);
183  if (A.Type == MCAtom::TextAtom)
184  IO.mapRequired("Content", A.Insts);
185  else if (A.Type == MCAtom::DataAtom)
186  IO.mapRequired("Content", A.Data);
187 }
188 
190  IO.mapRequired("Inst", I.Opcode);
191  IO.mapRequired("Size", I.Size);
192  IO.mapRequired("Ops", I.Operands);
193 }
194 
195 void
198  IO.mapRequired("Address", BB.Address);
199  IO.mapRequired("Preds", BB.Preds);
200  IO.mapRequired("Succs", BB.Succs);
201 }
202 
205  IO.mapRequired("Name", F.Name);
206  IO.mapRequired("BasicBlocks", F.BasicBlocks);
207 }
208 
211  IO.mapRequired("Atoms", M.Atoms);
212  IO.mapOptional("Functions", M.Functions);
213 }
214 
215 void
217  void *Ctx, raw_ostream &Out) {
218  InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
219 
220  // FIXME: Doesn't support FPImm and expr/inst, but do these make sense?
221  if (Val.MCOp.isImm())
222  Out << "I" << Val.MCOp.getImm();
223  else if (Val.MCOp.isReg())
224  Out << "R" << IRI->MRI.getName(Val.MCOp.getReg());
225  else
226  llvm_unreachable("Trying to output invalid MCOperand!");
227 }
228 
229 StringRef
231  MCModuleYAML::Operand &Val) {
232  InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
233  char Type = 0;
234  if (Scalar.size() >= 1)
235  Type = Scalar.front();
236  if (Type != 'R' && Type != 'I')
237  return "Operand must start with 'R' (register) or 'I' (immediate).";
238  if (Type == 'R') {
239  unsigned Reg;
240  if (!IRI->matchRegister(Scalar.substr(1), Reg))
241  return "Invalid register name.";
242  Val.MCOp = MCOperand::CreateReg(Reg);
243  } else if (Type == 'I') {
244  int64_t RIVal;
245  if (Scalar.substr(1).getAsInteger(10, RIVal))
246  return "Invalid immediate value.";
247  Val.MCOp = MCOperand::CreateImm(RIVal);
248  } else {
249  Val.MCOp = MCOperand();
250  }
251  return StringRef();
252 }
253 
255  const MCModuleYAML::OpcodeEnum &Val, void *Ctx, raw_ostream &Out) {
256  InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
257  Out << IRI->MII.getName(Val);
258 }
259 
260 StringRef
262  MCModuleYAML::OpcodeEnum &Val) {
263  InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
264  unsigned Opc;
265  if (!IRI->matchOpcode(Scalar, Opc))
266  return "Invalid instruction opcode.";
267  Val = Opc;
268  return "";
269 }
270 
271 } // end namespace yaml
272 
273 namespace {
274 
275 class MCModule2YAML {
276  const MCModule &MCM;
277  MCModuleYAML::Module YAMLModule;
278  void dumpAtom(const MCAtom *MCA);
279  void dumpFunction(const MCFunction *MCF);
280  void dumpBasicBlock(const MCBasicBlock *MCBB);
281 
282 public:
283  MCModule2YAML(const MCModule &MCM);
284  MCModuleYAML::Module &getYAMLModule();
285 };
286 
287 class YAML2MCModule {
288  MCModule &MCM;
289 
290 public:
291  YAML2MCModule(MCModule &MCM);
292  StringRef parse(const MCModuleYAML::Module &YAMLModule);
293 };
294 
295 } // end unnamed namespace
296 
297 MCModule2YAML::MCModule2YAML(const MCModule &MCM) : MCM(MCM), YAMLModule() {
298  for (MCModule::const_atom_iterator AI = MCM.atom_begin(), AE = MCM.atom_end();
299  AI != AE; ++AI)
300  dumpAtom(*AI);
301  for (MCModule::const_func_iterator FI = MCM.func_begin(), FE = MCM.func_end();
302  FI != FE; ++FI)
303  dumpFunction(*FI);
304 }
305 
306 void MCModule2YAML::dumpAtom(const MCAtom *MCA) {
307  YAMLModule.Atoms.resize(YAMLModule.Atoms.size() + 1);
308  MCModuleYAML::Atom &A = YAMLModule.Atoms.back();
309  A.Type = MCA->getKind();
310  A.StartAddress = MCA->getBeginAddr();
311  A.Size = MCA->getEndAddr() - MCA->getBeginAddr() + 1;
312  if (const MCTextAtom *TA = dyn_cast<MCTextAtom>(MCA)) {
313  const size_t InstCount = TA->size();
314  A.Insts.resize(InstCount);
315  for (size_t i = 0; i != InstCount; ++i) {
316  const MCDecodedInst &MCDI = TA->at(i);
317  A.Insts[i].Opcode = MCDI.Inst.getOpcode();
318  A.Insts[i].Size = MCDI.Size;
319  const unsigned OpCount = MCDI.Inst.getNumOperands();
320  A.Insts[i].Operands.resize(OpCount);
321  for (unsigned oi = 0; oi != OpCount; ++oi)
322  A.Insts[i].Operands[oi].MCOp = MCDI.Inst.getOperand(oi);
323  }
324  } else if (const MCDataAtom *DA = dyn_cast<MCDataAtom>(MCA)) {
325  A.Data = DA->getData();
326  } else {
327  llvm_unreachable("Unknown atom type.");
328  }
329 }
330 
331 void MCModule2YAML::dumpFunction(const MCFunction *MCF) {
332  YAMLModule.Functions.resize(YAMLModule.Functions.size() + 1);
333  MCModuleYAML::Function &F = YAMLModule.Functions.back();
334  F.Name = MCF->getName();
335  for (MCFunction::const_iterator BBI = MCF->begin(), BBE = MCF->end();
336  BBI != BBE; ++BBI) {
337  const MCBasicBlock *MCBB = *BBI;
338  F.BasicBlocks.resize(F.BasicBlocks.size() + 1);
339  MCModuleYAML::BasicBlock &BB = F.BasicBlocks.back();
340  BB.Address = MCBB->getInsts()->getBeginAddr();
341  for (MCBasicBlock::pred_const_iterator PI = MCBB->pred_begin(),
342  PE = MCBB->pred_end();
343  PI != PE; ++PI)
344  BB.Preds.push_back((*PI)->getInsts()->getBeginAddr());
345  for (MCBasicBlock::succ_const_iterator SI = MCBB->succ_begin(),
346  SE = MCBB->succ_end();
347  SI != SE; ++SI)
348  BB.Succs.push_back((*SI)->getInsts()->getBeginAddr());
349  }
350 }
351 
352 MCModuleYAML::Module &MCModule2YAML::getYAMLModule() { return YAMLModule; }
353 
354 YAML2MCModule::YAML2MCModule(MCModule &MCM) : MCM(MCM) {}
355 
356 StringRef YAML2MCModule::parse(const MCModuleYAML::Module &YAMLModule) {
357  typedef std::vector<MCModuleYAML::Atom>::const_iterator AtomIt;
358  typedef std::vector<MCModuleYAML::Inst>::const_iterator InstIt;
359  typedef std::vector<MCModuleYAML::Operand>::const_iterator OpIt;
360 
361  typedef DenseMap<uint64_t, MCTextAtom *> AddrToTextAtomTy;
362  AddrToTextAtomTy TAByAddr;
363 
364  for (AtomIt AI = YAMLModule.Atoms.begin(), AE = YAMLModule.Atoms.end();
365  AI != AE; ++AI) {
366  uint64_t StartAddress = AI->StartAddress;
367  if (AI->Size == 0)
368  return "Atoms can't be empty!";
369  uint64_t EndAddress = StartAddress + AI->Size - 1;
370  switch (AI->Type) {
371  case MCAtom::TextAtom: {
372  MCTextAtom *TA = MCM.createTextAtom(StartAddress, EndAddress);
373  TAByAddr[StartAddress] = TA;
374  for (InstIt II = AI->Insts.begin(), IE = AI->Insts.end(); II != IE;
375  ++II) {
376  MCInst MI;
377  MI.setOpcode(II->Opcode);
378  for (OpIt OI = II->Operands.begin(), OE = II->Operands.end(); OI != OE;
379  ++OI)
380  MI.addOperand(OI->MCOp);
381  TA->addInst(MI, II->Size);
382  }
383  break;
384  }
385  case MCAtom::DataAtom: {
386  MCDataAtom *DA = MCM.createDataAtom(StartAddress, EndAddress);
387  SmallVector<char, 64> Data;
388  raw_svector_ostream OS(Data);
389  AI->Data.writeAsBinary(OS);
390  OS.flush();
391  for (size_t i = 0, e = Data.size(); i != e; ++i)
392  DA->addData((uint8_t)Data[i]);
393  break;
394  }
395  }
396  }
397 
398  typedef std::vector<MCModuleYAML::Function>::const_iterator FuncIt;
399  typedef std::vector<MCModuleYAML::BasicBlock>::const_iterator BBIt;
400  typedef std::vector<yaml::Hex64>::const_iterator AddrIt;
401  for (FuncIt FI = YAMLModule.Functions.begin(),
402  FE = YAMLModule.Functions.end();
403  FI != FE; ++FI) {
404  MCFunction *MCFN = MCM.createFunction(FI->Name);
405  for (BBIt BBI = FI->BasicBlocks.begin(), BBE = FI->BasicBlocks.end();
406  BBI != BBE; ++BBI) {
407  AddrToTextAtomTy::const_iterator It = TAByAddr.find(BBI->Address);
408  if (It == TAByAddr.end())
409  return "Basic block start address doesn't match any text atom!";
410  MCFN->createBlock(*It->second);
411  }
412  for (BBIt BBI = FI->BasicBlocks.begin(), BBE = FI->BasicBlocks.end();
413  BBI != BBE; ++BBI) {
414  MCBasicBlock *MCBB = MCFN->find(BBI->Address);
415  if (!MCBB)
416  return "Couldn't find matching basic block in function.";
417  for (AddrIt PI = BBI->Preds.begin(), PE = BBI->Preds.end(); PI != PE;
418  ++PI) {
419  MCBasicBlock *Pred = MCFN->find(*PI);
420  if (!Pred)
421  return "Couldn't find predecessor basic block.";
422  MCBB->addPredecessor(Pred);
423  }
424  for (AddrIt SI = BBI->Succs.begin(), SE = BBI->Succs.end(); SI != SE;
425  ++SI) {
426  MCBasicBlock *Succ = MCFN->find(*SI);
427  if (!Succ)
428  return "Couldn't find predecessor basic block.";
429  MCBB->addSuccessor(Succ);
430  }
431  }
432  }
433  return "";
434 }
435 
437  const MCInstrInfo &MII, const MCRegisterInfo &MRI) {
438  MCModule2YAML Dumper(MCM);
439  InstrRegInfoHolder IRI(MII, MRI);
440  yaml::Output YOut(OS, (void *)&IRI);
441  YOut << Dumper.getYAMLModule();
442  return "";
443 }
444 
446  const MCInstrInfo &MII, const MCRegisterInfo &MRI) {
447  MCM.reset(new MCModule);
448  YAML2MCModule Parser(*MCM);
450  InstrRegInfoHolder IRI(MII, MRI);
451  yaml::Input YIn(YamlContent, (void *)&IRI);
452  YIn >> YAMLModule;
453  if (error_code ec = YIn.error())
454  return ec.message();
455  StringRef err = Parser.parse(YAMLModule);
456  if (!err.empty())
457  return err;
458  return "";
459 }
460 
461 } // end namespace llvm
SuccIterator< const TerminatorInst *, const BasicBlock > succ_const_iterator
Definition: Support/CFG.h:228
EnumValByNameTy RegEnumValueByName
size_t size() const
size - Get the string size.
Definition: StringRef.h:113
Various leaf nodes.
Definition: ISDOpcodes.h:60
bool isReg() const
Definition: MCInst.h:56
The main container class for the LLVM Intermediate Representation.
Definition: Module.h:112
StringRef substr(size_t Start, size_t N=npos) const
Definition: StringRef.h:392
iterator find(StringRef Key)
Definition: StringMap.h:291
F(f)
#define LLVM_YAML_IS_SEQUENCE_VECTOR(_type)
Definition: YAMLTraits.h:1050
std::vector< BasicBlock > BasicBlocks
Specialized YAMLIO scalar type for representing a binary blob.
Definition: YAML.h:64
#define llvm_unreachable(msg)
Definition: regcomp.c:56
std::vector< Atom > Atoms
std::vector< yaml::Hex64 > Succs
unsigned getReg() const
getReg - Returns the register number.
Definition: MCInst.h:63
llvm::enable_if_c< has_SequenceTraits< T >::value, void >::type mapOptional(const char *Key, T &Val)
Definition: YAMLTraits.h:392
StringMapConstIterator< ValueTy > const_iterator
Definition: StringMap.h:275
bool isImm() const
Definition: MCInst.h:57
void enumCase(T &Val, const char *Str, const T ConstVal)
Definition: YAMLTraits.h:353
object::yaml::BinaryRef Data
LLVM Basic Block Representation.
Definition: BasicBlock.h:72
void reset(T *P=0)
Definition: OwningPtr.h:51
const MCInstrInfo & MII
This file declares classes for handling the YAML representation of MCModule.
std::vector< Function > Functions
enable_if_c< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Definition: StringRef.h:337
uint64_t NextPowerOf2(uint64_t A)
Definition: MathExtras.h:546
std::vector< Inst > Insts
#define LLVM_YAML_STRONG_TYPEDEF(_base, _type)
Definition: YAMLTraits.h:891
std::vector< yaml::Hex64 > Preds
llvm::error_code error()
Definition: YAMLTraits.cpp:59
int64_t getImm() const
Definition: MCInst.h:74
std::vector< Operand > Operands
Represents a contiguous range of either instructions (a TextAtom) or data (a DataAtom). Address ranges are expressed as closed intervals.
Definition: MCAtom.h:34
StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
Dump a YAML representation of the MCModule MCM to OS.
#define I(x, y, z)
Definition: MD5.cpp:54
const MCModule & MCM
A completely disassembled object file or executable. It comprises a list of MCAtom's, each representing a contiguous range of either instructions or data. An MCModule is created using MCObjectDisassembler::buildModule.
Definition: MCModule.h:36
#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type)
Definition: YAMLTraits.h:1069
char front() const
front - Get the first character in the string.
Definition: StringRef.h:116
StringRef yaml2mcmodule(OwningPtr< MCModule > &MCM, StringRef YamlContent, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
Creates a new module and returns it in MCM.
LLVM Value Representation.
Definition: Value.h:66
MCAtom::AtomKind Type
MCModuleYAML::Module YAMLModule
void mapRequired(const char *Key, T &Val)
Definition: YAMLTraits.h:386
const MCRegisterInfo & MRI
iterator end()
Definition: StringMap.h:281
bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:110
EnumValByNameTy InstEnumValueByName