diff options
Diffstat (limited to 'contrib/llvm/lib/MC/MCAnalysis/MCModuleYAML.cpp')
-rw-r--r-- | contrib/llvm/lib/MC/MCAnalysis/MCModuleYAML.cpp | 464 |
1 files changed, 0 insertions, 464 deletions
diff --git a/contrib/llvm/lib/MC/MCAnalysis/MCModuleYAML.cpp b/contrib/llvm/lib/MC/MCAnalysis/MCModuleYAML.cpp deleted file mode 100644 index 876b06d..0000000 --- a/contrib/llvm/lib/MC/MCAnalysis/MCModuleYAML.cpp +++ /dev/null @@ -1,464 +0,0 @@ -//===- 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/MCAnalysis/MCModuleYAML.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/MC/MCAnalysis/MCAtom.h" -#include "llvm/MC/MCAnalysis/MCFunction.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/YAML.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.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; - 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 &); - static bool mustQuote(StringRef) { return false; } -}; - -template <> struct ScalarTraits<MCModuleYAML::OpcodeEnum> { - static void output(const MCModuleYAML::OpcodeEnum &, void *, - llvm::raw_ostream &); - static StringRef input(StringRef, void *, MCModuleYAML::OpcodeEnum &); - static bool mustQuote(StringRef) { return false; } -}; - -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(std::unique_ptr<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 (std::error_code ec = YIn.error()) - return ec.message(); - StringRef err = Parser.parse(YAMLModule); - if (!err.empty()) - return err; - return ""; -} - -} // end namespace llvm |