| //===-EDInst.cpp - LLVM Enhanced Disassembler -----------------------------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements the Enhanced Disassembly library's instruction class. | |
| // The instruction is responsible for vending the string representation, | |
| // individual tokens, and operands for a single instruction. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "EDInst.h" | |
| #include "EDDisassembler.h" | |
| #include "EDOperand.h" | |
| #include "EDToken.h" | |
| #include "llvm/MC/EDInstInfo.h" | |
| #include "llvm/MC/MCInst.h" | |
| using namespace llvm; | |
| EDInst::EDInst(llvm::MCInst *inst, | |
| uint64_t byteSize, | |
| EDDisassembler &disassembler, | |
| const llvm::EDInstInfo *info) : | |
| Disassembler(disassembler), | |
| Inst(inst), | |
| ThisInstInfo(info), | |
| ByteSize(byteSize), | |
| BranchTarget(-1), | |
| MoveSource(-1), | |
| MoveTarget(-1) { | |
| OperandOrder = ThisInstInfo->operandOrders[Disassembler.llvmSyntaxVariant()]; | |
| } | |
| EDInst::~EDInst() { | |
| unsigned int index; | |
| unsigned int numOperands = Operands.size(); | |
| for (index = 0; index < numOperands; ++index) | |
| delete Operands[index]; | |
| unsigned int numTokens = Tokens.size(); | |
| for (index = 0; index < numTokens; ++index) | |
| delete Tokens[index]; | |
| delete Inst; | |
| } | |
| uint64_t EDInst::byteSize() { | |
| return ByteSize; | |
| } | |
| int EDInst::stringify() { | |
| if (StringifyResult.valid()) | |
| return StringifyResult.result(); | |
| if (Disassembler.printInst(String, *Inst)) | |
| return StringifyResult.setResult(-1); | |
| String.push_back('\n'); | |
| return StringifyResult.setResult(0); | |
| } | |
| int EDInst::getString(const char*& str) { | |
| if (stringify()) | |
| return -1; | |
| str = String.c_str(); | |
| return 0; | |
| } | |
| unsigned EDInst::instID() { | |
| return Inst->getOpcode(); | |
| } | |
| bool EDInst::isBranch() { | |
| if (ThisInstInfo) | |
| return | |
| ThisInstInfo->instructionType == kInstructionTypeBranch || | |
| ThisInstInfo->instructionType == kInstructionTypeCall; | |
| else | |
| return false; | |
| } | |
| bool EDInst::isMove() { | |
| if (ThisInstInfo) | |
| return ThisInstInfo->instructionType == kInstructionTypeMove; | |
| else | |
| return false; | |
| } | |
| int EDInst::parseOperands() { | |
| if (ParseResult.valid()) | |
| return ParseResult.result(); | |
| if (!ThisInstInfo) | |
| return ParseResult.setResult(-1); | |
| unsigned int opIndex; | |
| unsigned int mcOpIndex = 0; | |
| for (opIndex = 0; opIndex < ThisInstInfo->numOperands; ++opIndex) { | |
| if (isBranch() && | |
| (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget)) { | |
| BranchTarget = opIndex; | |
| } | |
| else if (isMove()) { | |
| if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagSource) | |
| MoveSource = opIndex; | |
| else if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget) | |
| MoveTarget = opIndex; | |
| } | |
| EDOperand *operand = new EDOperand(Disassembler, *this, opIndex, mcOpIndex); | |
| Operands.push_back(operand); | |
| } | |
| return ParseResult.setResult(0); | |
| } | |
| int EDInst::branchTargetID() { | |
| if (parseOperands()) | |
| return -1; | |
| return BranchTarget; | |
| } | |
| int EDInst::moveSourceID() { | |
| if (parseOperands()) | |
| return -1; | |
| return MoveSource; | |
| } | |
| int EDInst::moveTargetID() { | |
| if (parseOperands()) | |
| return -1; | |
| return MoveTarget; | |
| } | |
| int EDInst::numOperands() { | |
| if (parseOperands()) | |
| return -1; | |
| return Operands.size(); | |
| } | |
| int EDInst::getOperand(EDOperand *&operand, unsigned int index) { | |
| if (parseOperands()) | |
| return -1; | |
| if (index >= Operands.size()) | |
| return -1; | |
| operand = Operands[index]; | |
| return 0; | |
| } | |
| int EDInst::tokenize() { | |
| if (TokenizeResult.valid()) | |
| return TokenizeResult.result(); | |
| if (ThisInstInfo == NULL) | |
| return TokenizeResult.setResult(-1); | |
| if (stringify()) | |
| return TokenizeResult.setResult(-1); | |
| return TokenizeResult.setResult(EDToken::tokenize(Tokens, | |
| String, | |
| OperandOrder, | |
| Disassembler)); | |
| } | |
| int EDInst::numTokens() { | |
| if (tokenize()) | |
| return -1; | |
| return Tokens.size(); | |
| } | |
| int EDInst::getToken(EDToken *&token, unsigned int index) { | |
| if (tokenize()) | |
| return -1; | |
| token = Tokens[index]; | |
| return 0; | |
| } | |
| #ifdef __BLOCKS__ | |
| int EDInst::visitTokens(EDTokenVisitor_t visitor) { | |
| if (tokenize()) | |
| return -1; | |
| tokvec_t::iterator iter; | |
| for (iter = Tokens.begin(); iter != Tokens.end(); ++iter) { | |
| int ret = visitor(*iter); | |
| if (ret == 1) | |
| return 0; | |
| if (ret != 0) | |
| return -1; | |
| } | |
| return 0; | |
| } | |
| #endif |