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