llvm.org GIT mirror llvm / 41ab14b
Add MCInstrAnalysis class. This allows the targets to specify own versions of MCInstrDescs functions. - Add overrides for ARM. - Teach llvm-objdump to use this instead of plain MCInstrDesc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137059 91177308-0d34-0410-b5e6-96231b3b80d8 Benjamin Kramer 9 years ago
7 changed file(s) with 176 addition(s) and 31 deletion(s). Raw diff Collapse all Expand all
0 //===-- llvm/MC/MCInstrAnalysis.h - InstrDesc target hooks ------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the MCInstrAnalysis class which the MCTargetDescs can
10 // derive from to give additional information to MC.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/MC/MCInst.h"
15 #include "llvm/MC/MCInstrDesc.h"
16 #include "llvm/MC/MCInstrInfo.h"
17
18 namespace llvm {
19
20 class MCInstrAnalysis {
21 protected:
22 friend class Target;
23 const MCInstrInfo *Info;
24
25 MCInstrAnalysis(const MCInstrInfo *Info) : Info(Info) {}
26 public:
27 virtual bool isBranch(const MCInst &Inst) const {
28 return Info->get(Inst.getOpcode()).isBranch();
29 }
30
31 virtual bool isConditionalBranch(const MCInst &Inst) const {
32 return Info->get(Inst.getOpcode()).isBranch();
33 }
34
35 virtual bool isUnconditionalBranch(const MCInst &Inst) const {
36 return Info->get(Inst.getOpcode()).isUnconditionalBranch();
37 }
38
39 virtual bool isIndirectBranch(const MCInst &Inst) const {
40 return Info->get(Inst.getOpcode()).isIndirectBranch();
41 }
42
43 virtual bool isReturn(const MCInst &Inst) const {
44 return Info->get(Inst.getOpcode()).isReturn();
45 }
46
47 /// evaluateBranch - Given a branch instruction try to get the address the
48 /// branch targets. Otherwise return -1.
49 virtual uint64_t
50 evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size) const;
51 };
52
53 }
1919 #define LLVM_TARGET_TARGETREGISTRY_H
2020
2121 #include "llvm/MC/MCCodeGenInfo.h"
22 #include "llvm/MC/MCInstrAnalysis.h"
2223 #include "llvm/ADT/Triple.h"
2324 #include
2425 #include
7374 Reloc::Model RM,
7475 CodeModel::Model CM);
7576 typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void);
77 typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo*Info);
7678 typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT);
7779 typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT,
7880 StringRef CPU,
146148 /// if registered.
147149 MCInstrInfoCtorFnTy MCInstrInfoCtorFn;
148150
151 /// MCInstrAnalysisCtorFn - Constructor function for this target's
152 /// MCInstrAnalysis, if registered.
153 MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn;
154
149155 /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo,
150156 /// if registered.
151157 MCRegInfoCtorFnTy MCRegInfoCtorFn;
278284 if (!MCInstrInfoCtorFn)
279285 return 0;
280286 return MCInstrInfoCtorFn();
287 }
288
289 /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation.
290 ///
291 MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const {
292 if (!MCInstrAnalysisCtorFn)
293 return new MCInstrAnalysis(Info);
294 return MCInstrAnalysisCtorFn(Info);
281295 }
282296
283297 /// createMCRegInfo - Create a MCRegisterInfo implementation.
556570 T.MCInstrInfoCtorFn = Fn;
557571 }
558572
573 /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for
574 /// the given target.
575 static void RegisterMCInstrAnalysis(Target &T,
576 Target::MCInstrAnalysisCtorFnTy Fn) {
577 // Ignore duplicate registration.
578 if (!T.MCInstrAnalysisCtorFn)
579 T.MCInstrAnalysisCtorFn = Fn;
580 }
581
559582 /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the
560583 /// given target.
561584 ///
0 //===-- MCInstrAnalysis.cpp - InstrDesc target hooks ------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/MC/MCInstrAnalysis.h"
10 using namespace llvm;
11
12 uint64_t MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
13 uint64_t Size) const {
14 if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType != MCOI::OPERAND_PCREL)
15 return -1ULL;
16
17 int64_t Imm = Inst.getOperand(0).getImm();
18 return Addr+Size+Imm;
19 }
1212
1313 #include "ARMMCTargetDesc.h"
1414 #include "ARMMCAsmInfo.h"
15 #include "ARMBaseInfo.h"
1516 #include "InstPrinter/ARMInstPrinter.h"
1617 #include "llvm/MC/MCInstrInfo.h"
1718 #include "llvm/MC/MCRegisterInfo.h"
158159 return 0;
159160 }
160161
162 namespace {
163
164 class ARMMCInstrAnalysis : public MCInstrAnalysis {
165 public:
166 ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
167 virtual bool isBranch(const MCInst &Inst) const {
168 // Don't flag "bx lr" as a branch.
169 return MCInstrAnalysis::isBranch(Inst) && (Inst.getOpcode() != ARM::BX ||
170 Inst.getOperand(0).getReg() != ARM::LR);
171 }
172
173 virtual bool isUnconditionalBranch(const MCInst &Inst) const {
174 // BCCs with the "always" predicate are unconditional branches.
175 if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
176 return true;
177 return MCInstrAnalysis::isUnconditionalBranch(Inst);
178 }
179
180 virtual bool isConditionalBranch(const MCInst &Inst) const {
181 // BCCs with the "always" predicate are unconditional branches.
182 if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
183 return false;
184 return MCInstrAnalysis::isConditionalBranch(Inst);
185 }
186
187 virtual bool isReturn(const MCInst &Inst) const {
188 // Recognize "bx lr" as return.
189 return Inst.getOpcode() == ARM::BX && Inst.getOperand(0).getReg()==ARM::LR;
190 }
191
192 uint64_t evaluateBranch(const MCInst &Inst, uint64_t Addr,
193 uint64_t Size) const {
194 // We only handle PCRel branches for now.
195 if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
196 return -1ULL;
197
198 int64_t Imm = Inst.getOperand(0).getImm();
199 // FIXME: This is not right for thumb.
200 return Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
201 }
202 };
203
204 }
205
206 static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
207 return new ARMMCInstrAnalysis(Info);
208 }
161209
162210 // Force static initialization.
163211 extern "C" void LLVMInitializeARMTargetMC() {
177225 TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo);
178226 TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo);
179227
228 TargetRegistry::RegisterMCInstrAnalysis(TheARMTarget,
229 createARMMCInstrAnalysis);
230 TargetRegistry::RegisterMCInstrAnalysis(TheThumbTarget,
231 createARMMCInstrAnalysis);
232
180233 // Register the MC subtarget info.
181234 TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget,
182235 ARM_MC::createARMMCSubtargetInfo);
1616 #include "llvm/MC/MCDisassembler.h"
1717 #include "llvm/MC/MCInst.h"
1818 #include "llvm/MC/MCInstPrinter.h"
19 #include "llvm/MC/MCInstrAnalysis.h"
1920 #include "llvm/MC/MCInstrDesc.h"
2021 #include "llvm/MC/MCInstrInfo.h"
2122 #include "llvm/Support/MemoryObject.h"
2728 MCFunction
2829 MCFunction::createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm,
2930 const MemoryObject &Region, uint64_t Start,
30 uint64_t End, const MCInstrInfo *InstrInfo,
31 uint64_t End, const MCInstrAnalysis *Ana,
3132 raw_ostream &DebugOut) {
3233 std::set Splits;
3334 Splits.insert(Start);
3940 MCInst Inst;
4041
4142 if (DisAsm->getInstruction(Inst, Size, Region, Index, DebugOut)) {
42 const MCInstrDesc &Desc = InstrInfo->get(Inst.getOpcode());
43 if (Desc.isBranch()) {
44 if (Desc.OpInfo[0].OperandType == MCOI::OPERAND_PCREL) {
45 int64_t Imm = Inst.getOperand(0).getImm();
46 // FIXME: Distinguish relocations from nop jumps.
47 if (Imm != 0) {
48 if (Index+Imm+Size >= End) {
49 Instructions.push_back(MCDecodedInst(Index, Size, Inst));
50 continue; // Skip branches that leave the function.
51 }
52 Splits.insert(Index+Imm+Size);
53 }
43 if (Ana->isBranch(Inst)) {
44 uint64_t targ = Ana->evaluateBranch(Inst, Index, Size);
45 // FIXME: Distinguish relocations from nop jumps.
46 if (targ != -1ULL && (targ == Index+Size || targ >= End)) {
47 Instructions.push_back(MCDecodedInst(Index, Size, Inst));
48 continue; // Skip branches that leave the function.
5449 }
50 if (targ != -1ULL)
51 Splits.insert(targ);
5552 Splits.insert(Index+Size);
56 } else if (Desc.isReturn()) {
53 } else if (Ana->isReturn(Inst)) {
5754 Splits.insert(Index+Size);
5855 }
5956
8986 MCBasicBlock &BB = i->second;
9087 if (BB.getInsts().empty()) continue;
9188 const MCDecodedInst &Inst = BB.getInsts().back();
92 const MCInstrDesc &Desc = InstrInfo->get(Inst.Inst.getOpcode());
9389
94 if (Desc.isBranch()) {
95 // PCRel branch, we know the destination.
96 if (Desc.OpInfo[0].OperandType == MCOI::OPERAND_PCREL) {
97 int64_t Imm = Inst.Inst.getOperand(0).getImm();
98 if (Imm != 0)
99 BB.addSucc(&f.getBlockAtAddress(Inst.Address+Inst.Size+Imm));
100 // Conditional branches can also fall through to the next block.
101 if (Desc.isConditionalBranch() && llvm::next(i) != e)
102 BB.addSucc(&llvm::next(i)->second);
103 } else {
90 if (Ana->isBranch(Inst.Inst)) {
91 uint64_t targ = Ana->evaluateBranch(Inst.Inst, Inst.Address, Inst.Size);
92 if (targ == -1ULL) {
10493 // Indirect branch. Bail and add all blocks of the function as a
10594 // successor.
10695 for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i)
10796 BB.addSucc(&i->second);
108 }
97 } else if (targ != Inst.Address+Inst.Size)
98 BB.addSucc(&f.getBlockAtAddress(targ));
99 // Conditional branches can also fall through to the next block.
100 if (Ana->isConditionalBranch(Inst.Inst) && llvm::next(i) != e)
101 BB.addSucc(&llvm::next(i)->second);
109102 } else {
110103 // No branch. Fall through to the next block.
111 if (!Desc.isReturn() && llvm::next(i) != e)
104 if (!Ana->isReturn(Inst.Inst) && llvm::next(i) != e)
112105 BB.addSucc(&llvm::next(i)->second);
113106 }
114107 }
1919 namespace llvm {
2020
2121 class MCDisassembler;
22 class MCInstrInfo;
22 class MCInstrAnalysis;
2323 class MemoryObject;
2424 class raw_ostream;
2525
6767 static MCFunction
6868 createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm,
6969 const MemoryObject &Region, uint64_t Start, uint64_t End,
70 const MCInstrInfo *InstrInfo, raw_ostream &DebugOut);
70 const MCInstrAnalysis *Ana, raw_ostream &DebugOut);
7171
7272 typedef MapTy::iterator iterator;
7373 iterator begin() { return Blocks.begin(); }
164164 return;
165165 }
166166 const MCInstrInfo *InstrInfo = TheTarget->createMCInstrInfo();
167 OwningPtr
168 InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo));
167169
168170 outs() << '\n';
169171 outs() << Filename
269271 // Create CFG and use it for disassembly.
270272 MCFunction f =
271273 MCFunction::createFunctionFromMC(Symbols[si].second, DisAsm.get(),
272 memoryObject, Start, End, InstrInfo,
273 DebugOut);
274 memoryObject, Start, End,
275 InstrAnalysis.get(), DebugOut);
274276
275277 for (MCFunction::iterator fi = f.begin(), fe = f.end(); fi != fe; ++fi){
276278 bool hasPreds = false;