diff options
Diffstat (limited to 'include')
40 files changed, 1539 insertions, 650 deletions
diff --git a/include/llvm/Analysis/BlockFrequency.h b/include/llvm/Analysis/BlockFrequency.h new file mode 100644 index 0000000..c4b1e08 --- /dev/null +++ b/include/llvm/Analysis/BlockFrequency.h @@ -0,0 +1,53 @@ +//========-------- BlockFrequency.h - Block Frequency Analysis -------========// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Loops should be simplified before this analysis. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_BLOCKFREQUENCY_H +#define LLVM_ANALYSIS_BLOCKFREQUENCY_H + +#include "llvm/Pass.h" +#include <climits> + +namespace llvm { + +class BranchProbabilityInfo; +template<class BlockT, class FunctionT, class BranchProbInfoT> +class BlockFrequencyImpl; + +/// BlockFrequency pass uses BlockFrequencyImpl implementation to estimate +/// IR basic block frequencies. +class BlockFrequency : public FunctionPass { + + BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> *BFI; + +public: + static char ID; + + BlockFrequency(); + + ~BlockFrequency(); + + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool runOnFunction(Function &F); + + /// getblockFreq - Return block frequency. Never return 0, value must be + /// positive. Please note that initial frequency is equal to 1024. It means + /// that we should not rely on the value itself, but only on the comparison to + /// the other block frequencies. We do this to avoid using of the floating + /// points. + uint32_t getBlockFreq(BasicBlock *BB); +}; + +} + +#endif diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h new file mode 100644 index 0000000..cef375f --- /dev/null +++ b/include/llvm/Analysis/BlockFrequencyImpl.h @@ -0,0 +1,345 @@ +//===---- BlockFrequencyImpl.h - Machine Block Frequency Implementation ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Shared implementation of BlockFrequency for IR and Machine Instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H +#define LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H + +#include "llvm/BasicBlock.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Support/BranchProbability.h" +#include "llvm/Support/Debug.h" +#include <vector> +#include <sstream> +#include <string> + +namespace llvm { + + +class BlockFrequency; +/// BlockFrequencyImpl implements block frequency algorithm for IR and +/// Machine Instructions. Algorithm starts with value 1024 (START_FREQ) +/// for the entry block and then propagates frequencies using branch weights +/// from (Machine)BranchProbabilityInfo. LoopInfo is not required because +/// algorithm can find "backedges" by itself. +template<class BlockT, class FunctionT, class BlockProbInfoT> +class BlockFrequencyImpl { + + DenseMap<BlockT *, uint32_t> Freqs; + + BlockProbInfoT *BPI; + + FunctionT *Fn; + + typedef GraphTraits< Inverse<BlockT *> > GT; + + static const uint32_t START_FREQ = 1024; + + std::string getBlockName(BasicBlock *BB) const { + return BB->getNameStr(); + } + + std::string getBlockName(MachineBasicBlock *MBB) const { + std::stringstream ss; + ss << "BB#" << MBB->getNumber(); + const BasicBlock *BB = MBB->getBasicBlock(); + + if (BB) + ss << " derived from LLVM BB " << BB->getNameStr(); + + return ss.str(); + } + + void setBlockFreq(BlockT *BB, uint32_t Freq) { + Freqs[BB] = Freq; + DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = " << Freq << "\n"); + } + + /// getEdgeFreq - Return edge frequency based on SRC frequency and Src -> Dst + /// edge probability. + uint32_t getEdgeFreq(BlockT *Src, BlockT *Dst) const { + BranchProbability Prob = BPI->getEdgeProbability(Src, Dst); + uint64_t N = Prob.getNumerator(); + uint64_t D = Prob.getDenominator(); + uint64_t Res = (N * getBlockFreq(Src)) / D; + + assert(Res <= UINT32_MAX); + return (uint32_t) Res; + } + + /// incBlockFreq - Increase BB block frequency by FREQ. + /// + void incBlockFreq(BlockT *BB, uint32_t Freq) { + Freqs[BB] += Freq; + DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += " << Freq + << " --> " << Freqs[BB] << "\n"); + } + + /// divBlockFreq - Divide BB block frequency by PROB. If Prob = 0 do nothing. + /// + void divBlockFreq(BlockT *BB, BranchProbability Prob) { + uint64_t N = Prob.getNumerator(); + assert(N && "Illegal division by zero!"); + uint64_t D = Prob.getDenominator(); + uint64_t Freq = (Freqs[BB] * D) / N; + + // Should we assert it? + if (Freq > UINT32_MAX) + Freq = UINT32_MAX; + + Freqs[BB] = (uint32_t) Freq; + DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") /= (" << Prob + << ") --> " << Freqs[BB] << "\n"); + } + + // All blocks in postorder. + std::vector<BlockT *> POT; + + // Map Block -> Position in reverse-postorder list. + DenseMap<BlockT *, unsigned> RPO; + + // Cycle Probability for each bloch. + DenseMap<BlockT *, uint32_t> CycleProb; + + // (reverse-)postorder traversal iterators. + typedef typename std::vector<BlockT *>::iterator pot_iterator; + typedef typename std::vector<BlockT *>::reverse_iterator rpot_iterator; + + pot_iterator pot_begin() { return POT.begin(); } + pot_iterator pot_end() { return POT.end(); } + + rpot_iterator rpot_begin() { return POT.rbegin(); } + rpot_iterator rpot_end() { return POT.rend(); } + + rpot_iterator rpot_at(BlockT *BB) { + rpot_iterator I = rpot_begin(); + unsigned idx = RPO[BB]; + assert(idx); + std::advance(I, idx - 1); + + assert(*I == BB); + return I; + } + + + /// Return a probability of getting to the DST block through SRC->DST edge. + /// + BranchProbability getBackEdgeProbability(BlockT *Src, BlockT *Dst) const { + uint32_t N = getEdgeFreq(Src, Dst); + uint32_t D = getBlockFreq(Dst); + + return BranchProbability(N, D); + } + + /// isReachable - Returns if BB block is reachable from the entry. + /// + bool isReachable(BlockT *BB) { + return RPO.count(BB); + } + + /// isBackedge - Return if edge Src -> Dst is a backedge. + /// + bool isBackedge(BlockT *Src, BlockT *Dst) { + assert(isReachable(Src)); + assert(isReachable(Dst)); + + unsigned a = RPO[Src]; + unsigned b = RPO[Dst]; + + return a > b; + } + + /// getSingleBlockPred - return single BB block predecessor or NULL if + /// BB has none or more predecessors. + BlockT *getSingleBlockPred(BlockT *BB) { + typename GT::ChildIteratorType + PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB), + PE = GraphTraits< Inverse<BlockT *> >::child_end(BB); + + if (PI == PE) + return 0; + + BlockT *Pred = *PI; + + ++PI; + if (PI != PE) + return 0; + + return Pred; + } + + void doBlock(BlockT *BB, BlockT *LoopHead, + SmallPtrSet<BlockT *, 8> &BlocksInLoop) { + + DEBUG(dbgs() << "doBlock(" << getBlockName(BB) << ")\n"); + setBlockFreq(BB, 0); + + if (BB == LoopHead) { + setBlockFreq(BB, START_FREQ); + return; + } + + if(BlockT *Pred = getSingleBlockPred(BB)) { + if (BlocksInLoop.count(Pred)) + setBlockFreq(BB, getEdgeFreq(Pred, BB)); + // TODO: else? irreducible, ignore it for now. + return; + } + + bool isInLoop = false; + bool isLoopHead = false; + + for (typename GT::ChildIteratorType + PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB), + PE = GraphTraits< Inverse<BlockT *> >::child_end(BB); + PI != PE; ++PI) { + BlockT *Pred = *PI; + + if (isReachable(Pred) && isBackedge(Pred, BB)) { + isLoopHead = true; + } else if (BlocksInLoop.count(Pred)) { + incBlockFreq(BB, getEdgeFreq(Pred, BB)); + isInLoop = true; + } + // TODO: else? irreducible. + } + + if (!isInLoop) + return; + + if (!isLoopHead) + return; + + assert(START_FREQ >= CycleProb[BB]); + uint32_t CProb = CycleProb[BB]; + uint32_t Numerator = START_FREQ - CProb ? START_FREQ - CProb : 1; + divBlockFreq(BB, BranchProbability(Numerator, START_FREQ)); + } + + /// doLoop - Propagate block frequency down throught the loop. + void doLoop(BlockT *Head, BlockT *Tail) { + DEBUG(dbgs() << "doLoop(" << getBlockName(Head) << ", " + << getBlockName(Tail) << ")\n"); + + SmallPtrSet<BlockT *, 8> BlocksInLoop; + + for (rpot_iterator I = rpot_at(Head), E = rpot_end(); I != E; ++I) { + BlockT *BB = *I; + doBlock(BB, Head, BlocksInLoop); + + BlocksInLoop.insert(BB); + } + + // Compute loop's cyclic probability using backedges probabilities. + for (typename GT::ChildIteratorType + PI = GraphTraits< Inverse<BlockT *> >::child_begin(Head), + PE = GraphTraits< Inverse<BlockT *> >::child_end(Head); + PI != PE; ++PI) { + BlockT *Pred = *PI; + assert(Pred); + if (isReachable(Pred) && isBackedge(Pred, Head)) { + BranchProbability Prob = getBackEdgeProbability(Pred, Head); + uint64_t N = Prob.getNumerator(); + uint64_t D = Prob.getDenominator(); + uint64_t Res = (N * START_FREQ) / D; + + assert(Res <= UINT32_MAX); + CycleProb[Head] += (uint32_t) Res; + } + } + } + + friend class BlockFrequency; + + void doFunction(FunctionT *fn, BlockProbInfoT *bpi) { + Fn = fn; + BPI = bpi; + + // Clear everything. + RPO.clear(); + POT.clear(); + CycleProb.clear(); + Freqs.clear(); + + BlockT *EntryBlock = fn->begin(); + + copy(po_begin(EntryBlock), po_end(EntryBlock), back_inserter(POT)); + + unsigned RPOidx = 0; + for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) { + BlockT *BB = *I; + RPO[BB] = ++RPOidx; + DEBUG(dbgs() << "RPO[" << getBlockName(BB) << "] = " << RPO[BB] << "\n"); + } + + // Travel over all blocks in postorder. + for (pot_iterator I = pot_begin(), E = pot_end(); I != E; ++I) { + BlockT *BB = *I; + BlockT *LastTail = 0; + DEBUG(dbgs() << "POT: " << getBlockName(BB) << "\n"); + + for (typename GT::ChildIteratorType + PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB), + PE = GraphTraits< Inverse<BlockT *> >::child_end(BB); + PI != PE; ++PI) { + + BlockT *Pred = *PI; + if (isReachable(Pred) && isBackedge(Pred, BB) + && (!LastTail || RPO[Pred] > RPO[LastTail])) + LastTail = Pred; + } + + if (LastTail) + doLoop(BB, LastTail); + } + + // At the end assume the whole function as a loop, and travel over it once + // again. + doLoop(*(rpot_begin()), *(pot_begin())); + } + +public: + /// getBlockFreq - Return block frequency. Never return 0, value must be + /// positive. + uint32_t getBlockFreq(BlockT *BB) const { + typename DenseMap<BlockT *, uint32_t>::const_iterator I = Freqs.find(BB); + if (I != Freqs.end()) + return I->second ? I->second : 1; + return 1; + } + + void print(raw_ostream &OS) const { + OS << "\n\n---- Block Freqs ----\n"; + for (typename FunctionT::iterator I = Fn->begin(), E = Fn->end(); I != E;) { + BlockT *BB = I++; + OS << " " << getBlockName(BB) << " = " << getBlockFreq(BB) << "\n"; + + for (typename GraphTraits<BlockT *>::ChildIteratorType + SI = GraphTraits<BlockT *>::child_begin(BB), + SE = GraphTraits<BlockT *>::child_end(BB); SI != SE; ++SI) { + BlockT *Succ = *SI; + OS << " " << getBlockName(BB) << " -> " << getBlockName(Succ) + << " = " << getEdgeFreq(BB, Succ) << "\n"; + } + } + } + + void dump() const { + print(dbgs()); + } +}; + +} + +#endif diff --git a/include/llvm/Analysis/DIBuilder.h b/include/llvm/Analysis/DIBuilder.h index 96c6587..a706cc8 100644 --- a/include/llvm/Analysis/DIBuilder.h +++ b/include/llvm/Analysis/DIBuilder.h @@ -135,6 +135,7 @@ namespace llvm { unsigned Flags); /// createMemberType - Create debugging information entry for a member. + /// @param Scope Member scope. /// @param Name Member name. /// @param File File where this member is defined. /// @param LineNo Line number. @@ -143,7 +144,7 @@ namespace llvm { /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. - DIType createMemberType(StringRef Name, DIFile File, + DIType createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType Ty); diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 39d378e..647a7dc 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -30,6 +30,10 @@ namespace llvm { /// memory. class SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> { ScalarEvolution &SE; + + // New instructions receive a name to identifies them with the current pass. + const char* IVName; + std::map<std::pair<const SCEV *, Instruction *>, AssertingVH<Value> > InsertedExpressions; std::set<AssertingVH<Value> > InsertedValues; @@ -67,8 +71,8 @@ namespace llvm { public: /// SCEVExpander - Construct a SCEVExpander in "canonical" mode. - explicit SCEVExpander(ScalarEvolution &se) - : SE(se), IVIncInsertLoop(0), CanonicalMode(true), + explicit SCEVExpander(ScalarEvolution &se, const char *name) + : SE(se), IVName(name), IVIncInsertLoop(0), CanonicalMode(true), Builder(se.getContext(), TargetFolder(se.TD)) {} /// clear - Erase the contents of the InsertedExpressions map so that users diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 6df1693..d4354bb 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -158,6 +158,10 @@ namespace llvm { return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup); } + /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer + /// are lifetime markers. + bool onlyUsedByLifetimeMarkers(const Value *V); + } // end namespace llvm #endif diff --git a/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h index b02c249..3b953c0 100644 --- a/include/llvm/BasicBlock.h +++ b/include/llvm/BasicBlock.h @@ -138,6 +138,12 @@ public: return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbg(); } + // Same as above, but also skip lifetime intrinsics. + Instruction* getFirstNonPHIOrDbgOrLifetime(); + const Instruction* getFirstNonPHIOrDbgOrLifetime() const { + return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime(); + } + /// removeFromParent - This method unlinks 'this' from the containing /// function, but does not delete it. /// diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 779ef5f..0ca3ad1 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -375,10 +375,12 @@ public: // Check that the block wasn't partially defined, and that the offset isn't // bogus. - if (AtEndOfStream() || NextChar+NumWords*4 > BitStream->getLastChar()) + const unsigned char *const SkipTo = NextChar + NumWords*4; + if (AtEndOfStream() || SkipTo > BitStream->getLastChar() || + SkipTo < BitStream->getFirstChar()) return true; - NextChar += NumWords*4; + NextChar = SkipTo; return false; } diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index c931261..098dd0b 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -39,8 +39,6 @@ namespace { (void) llvm::createGreedyRegisterAllocator(); (void) llvm::createDefaultPBQPRegisterAllocator(); - (void) llvm::createSimpleRegisterCoalescer(); - llvm::linkOcamlGC(); llvm::linkShadowStackGC(); diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index f56c053..6e08f7b 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -345,7 +345,7 @@ public: /// CreateMachineInstr - Allocate a new MachineInstr. Use this instead /// of `new MachineInstr'. /// - MachineInstr *CreateMachineInstr(const TargetInstrDesc &TID, + MachineInstr *CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImp = false); diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index c36dd69..788d149 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -17,7 +17,7 @@ #define LLVM_CODEGEN_MACHINEINSTR_H #include "llvm/CodeGen/MachineOperand.h" -#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/MC/MCInstrDesc.h" #include "llvm/Target/TargetOpcodes.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" @@ -30,7 +30,6 @@ namespace llvm { template <typename T> class SmallVectorImpl; class AliasAnalysis; -class TargetInstrDesc; class TargetInstrInfo; class TargetRegisterInfo; class MachineFunction; @@ -57,7 +56,7 @@ public: // function frame setup code. }; private: - const TargetInstrDesc *TID; // Instruction descriptor. + const MCInstrDesc *MCID; // Instruction descriptor. uint16_t NumImplicitOps; // Number of implicit operands (which // are determined at construction time). @@ -94,7 +93,7 @@ private: MachineInstr(MachineFunction &, const MachineInstr &); /// MachineInstr ctor - This constructor creates a dummy MachineInstr with - /// TID NULL and no operands. + /// MCID NULL and no operands. MachineInstr(); // The next two constructors have DebugLoc and non-DebugLoc versions; @@ -103,25 +102,25 @@ private: /// MachineInstr ctor - This constructor creates a MachineInstr and adds the /// implicit operands. It reserves space for the number of operands specified - /// by the TargetInstrDesc. The version with a DebugLoc should be preferred. - explicit MachineInstr(const TargetInstrDesc &TID, bool NoImp = false); + /// by the MCInstrDesc. The version with a DebugLoc should be preferred. + explicit MachineInstr(const MCInstrDesc &MCID, bool NoImp = false); /// MachineInstr ctor - Work exactly the same as the ctor above, except that /// the MachineInstr is created and added to the end of the specified basic /// block. The version with a DebugLoc should be preferred. - MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &TID); + MachineInstr(MachineBasicBlock *MBB, const MCInstrDesc &MCID); /// MachineInstr ctor - This constructor create a MachineInstr and add the /// implicit operands. It reserves space for number of operands specified by - /// TargetInstrDesc. An explicit DebugLoc is supplied. - explicit MachineInstr(const TargetInstrDesc &TID, const DebugLoc dl, + /// MCInstrDesc. An explicit DebugLoc is supplied. + explicit MachineInstr(const MCInstrDesc &MCID, const DebugLoc dl, bool NoImp = false); /// MachineInstr ctor - Work exactly the same as the ctor above, except that /// the MachineInstr is created and added to the end of the specified basic /// block. MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, - const TargetInstrDesc &TID); + const MCInstrDesc &MCID); ~MachineInstr(); @@ -183,11 +182,11 @@ public: /// getDesc - Returns the target instruction descriptor of this /// MachineInstr. - const TargetInstrDesc &getDesc() const { return *TID; } + const MCInstrDesc &getDesc() const { return *MCID; } /// getOpcode - Returns the opcode of this MachineInstr. /// - int getOpcode() const { return TID->Opcode; } + int getOpcode() const { return MCID->Opcode; } /// Access to explicit operands of the instruction. /// @@ -279,6 +278,9 @@ public: bool isCopy() const { return getOpcode() == TargetOpcode::COPY; } + bool isFullCopy() const { + return isCopy() && !getOperand(0).getSubReg() && !getOperand(1).getSubReg(); + } /// isCopyLike - Return true if the instruction behaves like a copy. /// This does not include native copy instructions. @@ -464,8 +466,8 @@ public: /// hasUnmodeledSideEffects - Return true if this instruction has side /// effects that are not modeled by mayLoad / mayStore, etc. - /// For all instructions, the property is encoded in TargetInstrDesc::Flags - /// (see TargetInstrDesc::hasUnmodeledSideEffects(). The only exception is + /// For all instructions, the property is encoded in MCInstrDesc::Flags + /// (see MCInstrDesc::hasUnmodeledSideEffects(). The only exception is /// INLINEASM instruction, in which case the side effect property is encoded /// in one of its operands (see InlineAsm::Extra_HasSideEffect). /// @@ -497,7 +499,7 @@ public: /// setDesc - Replace the instruction descriptor (thus opcode) of /// the current instruction with a new one. /// - void setDesc(const TargetInstrDesc &tid) { TID = &tid; } + void setDesc(const MCInstrDesc &tid) { MCID = &tid; } /// setDebugLoc - Replace current source information with new such. /// Avoid using this, the constructor argument is preferable. diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index c8183a3..b989027 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -22,7 +22,7 @@ namespace llvm { -class TargetInstrDesc; +class MCInstrDesc; class MDNode; namespace RegState { @@ -77,6 +77,11 @@ public: return *this; } + const MachineInstrBuilder &addCImm(const ConstantInt *Val) const { + MI->addOperand(MachineOperand::CreateCImm(Val)); + return *this; + } + const MachineInstrBuilder &addFPImm(const ConstantFP *Val) const { MI->addOperand(MachineOperand::CreateFPImm(Val)); return *this; @@ -175,8 +180,8 @@ public: /// inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, - const TargetInstrDesc &TID) { - return MachineInstrBuilder(MF.CreateMachineInstr(TID, DL)); + const MCInstrDesc &MCID) { + return MachineInstrBuilder(MF.CreateMachineInstr(MCID, DL)); } /// BuildMI - This version of the builder sets up the first operand as a @@ -184,9 +189,9 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, /// inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, unsigned DestReg) { - return MachineInstrBuilder(MF.CreateMachineInstr(TID, DL)) + return MachineInstrBuilder(MF.CreateMachineInstr(MCID, DL)) .addReg(DestReg, RegState::Define); } @@ -197,9 +202,9 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, DebugLoc DL, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, unsigned DestReg) { - MachineInstr *MI = BB.getParent()->CreateMachineInstr(TID, DL); + MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL); BB.insert(I, MI); return MachineInstrBuilder(MI).addReg(DestReg, RegState::Define); } @@ -211,8 +216,8 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, DebugLoc DL, - const TargetInstrDesc &TID) { - MachineInstr *MI = BB.getParent()->CreateMachineInstr(TID, DL); + const MCInstrDesc &MCID) { + MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL); BB.insert(I, MI); return MachineInstrBuilder(MI); } @@ -223,8 +228,8 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, /// inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, DebugLoc DL, - const TargetInstrDesc &TID) { - return BuildMI(*BB, BB->end(), DL, TID); + const MCInstrDesc &MCID) { + return BuildMI(*BB, BB->end(), DL, MCID); } /// BuildMI - This version of the builder inserts the newly-built @@ -233,9 +238,9 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, /// inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, DebugLoc DL, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, unsigned DestReg) { - return BuildMI(*BB, BB->end(), DL, TID, DestReg); + return BuildMI(*BB, BB->end(), DL, MCID, DestReg); } inline unsigned getDefRegState(bool B) { diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 140c6e8..fdef574 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -21,6 +21,7 @@ namespace llvm { class BlockAddress; class ConstantFP; +class ConstantInt; class GlobalValue; class MachineBasicBlock; class MachineInstr; @@ -38,6 +39,7 @@ public: enum MachineOperandType { MO_Register, ///< Register operand. MO_Immediate, ///< Immediate operand + MO_CImmediate, ///< Immediate >64bit operand MO_FPImmediate, ///< Floating-point immediate operand MO_MachineBasicBlock, ///< MachineBasicBlock reference MO_FrameIndex, ///< Abstract Stack Frame Index @@ -111,6 +113,7 @@ private: union { MachineBasicBlock *MBB; // For MO_MachineBasicBlock. const ConstantFP *CFP; // For MO_FPImmediate. + const ConstantInt *CI; // For MO_CImmediate. Integers > 64bit. int64_t ImmVal; // For MO_Immediate. const MDNode *MD; // For MO_Metadata. MCSymbol *Sym; // For MO_MCSymbol @@ -173,6 +176,8 @@ public: bool isReg() const { return OpKind == MO_Register; } /// isImm - Tests if this is a MO_Immediate operand. bool isImm() const { return OpKind == MO_Immediate; } + /// isCImm - Test if t his is a MO_CImmediate operand. + bool isCImm() const { return OpKind == MO_CImmediate; } /// isFPImm - Tests if this is a MO_FPImmediate operand. bool isFPImm() const { return OpKind == MO_FPImmediate; } /// isMBB - Tests if this is a MO_MachineBasicBlock operand. @@ -333,6 +338,11 @@ public: return Contents.ImmVal; } + const ConstantInt *getCImm() const { + assert(isCImm() && "Wrong MachineOperand accessor"); + return Contents.CI; + } + const ConstantFP *getFPImm() const { assert(isFPImm() && "Wrong MachineOperand accessor"); return Contents.CFP; @@ -440,6 +450,12 @@ public: return Op; } + static MachineOperand CreateCImm(const ConstantInt *CI) { + MachineOperand Op(MachineOperand::MO_CImmediate); + Op.Contents.CI = CI; + return Op; + } + static MachineOperand CreateFPImm(const ConstantFP *CFP) { MachineOperand Op(MachineOperand::MO_FPImmediate); Op.Contents.CFP = CFP; diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 74df8da..8754108 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -32,11 +32,6 @@ class MachineRegisterInfo { IndexedMap<std::pair<const TargetRegisterClass*, MachineOperand*>, VirtReg2IndexFunctor> VRegInfo; - /// RegClassVRegMap - This vector acts as a map from TargetRegisterClass to - /// virtual registers. For each target register class, it keeps a list of - /// virtual registers belonging to the class. - std::vector<unsigned> *RegClass2VRegMap; - /// RegAllocHints - This vector records register allocation hints for virtual /// registers. For each virtual register, it keeps a register and hint type /// pair making up the allocation hint. Hint type is target specific except @@ -216,13 +211,6 @@ public: /// unsigned getNumVirtRegs() const { return VRegInfo.size(); } - /// getRegClassVirtRegs - Return the list of virtual registers of the given - /// target register class. - const std::vector<unsigned> & - getRegClassVirtRegs(const TargetRegisterClass *RC) const { - return RegClass2VRegMap[RC->getID()]; - } - /// setRegAllocationHint - Specify a register allocation hint for the /// specified virtual register. void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) { diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 53aee7a..e7928cb 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -73,16 +73,9 @@ namespace llvm { /// This pass is still in development extern char &StrongPHIEliminationID; - extern char &PreAllocSplittingID; - /// LiveStacks pass. An analysis keeping track of the liveness of stack slots. extern char &LiveStacksID; - /// SimpleRegisterCoalescing pass. Aggressively coalesces every register - /// copy it can. - /// - extern char &SimpleRegisterCoalescingID; - /// TwoAddressInstruction pass - This pass reduces two-address instructions to /// use two operands. This destroys SSA information but it is desired by /// register allocators. @@ -132,10 +125,10 @@ namespace llvm { /// FunctionPass *createDefaultPBQPRegisterAllocator(); - /// SimpleRegisterCoalescing Pass - Coalesce all copies possible. Can run + /// RegisterCoalescer Pass - Coalesce all copies possible. Can run /// independently of the register allocator. /// - RegisterCoalescer *createSimpleRegisterCoalescer(); + RegisterCoalescer *createRegisterCoalescer(); /// PrologEpilogCodeInserter Pass - This pass inserts prolog and epilog code, /// and eliminates abstract frame references. diff --git a/include/llvm/CodeGen/RegisterCoalescer.h b/include/llvm/CodeGen/RegisterCoalescer.h deleted file mode 100644 index af0b394..0000000 --- a/include/llvm/CodeGen/RegisterCoalescer.h +++ /dev/null @@ -1,244 +0,0 @@ -//===-- RegisterCoalescer.h - Register Coalescing Interface ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the abstract interface for register coalescers, -// allowing them to interact with and query register allocators. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/IncludeFile.h" -#include "llvm/CodeGen/LiveInterval.h" -#include "llvm/ADT/SmallPtrSet.h" - -#ifndef LLVM_CODEGEN_REGISTER_COALESCER_H -#define LLVM_CODEGEN_REGISTER_COALESCER_H - -namespace llvm { - - class MachineFunction; - class RegallocQuery; - class AnalysisUsage; - class MachineInstr; - class TargetRegisterInfo; - class TargetRegisterClass; - class TargetInstrInfo; - - /// An abstract interface for register coalescers. Coalescers must - /// implement this interface to be part of the coalescer analysis - /// group. - class RegisterCoalescer { - public: - static char ID; // Class identification, replacement for typeinfo - RegisterCoalescer() {} - virtual ~RegisterCoalescer(); // We want to be subclassed - - /// Run the coalescer on this function, providing interference - /// data to query. Return whether we removed any copies. - virtual bool coalesceFunction(MachineFunction &mf, - RegallocQuery &ifd) = 0; - - /// Reset state. Can be used to allow a coalescer run by - /// PassManager to be run again by the register allocator. - virtual void reset(MachineFunction &mf) {} - - /// Register allocators must call this from their own - /// getAnalysisUsage to cover the case where the coalescer is not - /// a Pass in the proper sense and isn't managed by PassManager. - /// PassManager needs to know which analyses to make available and - /// which to invalidate when running the register allocator or any - /// pass that might call coalescing. The long-term solution is to - /// allow hierarchies of PassManagers. - virtual void getAnalysisUsage(AnalysisUsage &AU) const {} - }; - - /// An abstract interface for register allocators to interact with - /// coalescers - /// - /// Example: - /// - /// This is simply an example of how to use the RegallocQuery - /// interface. It is not meant to be used in production. - /// - /// class LinearScanRegallocQuery : public RegallocQuery { - /// private: - /// const LiveIntervals \&li; - /// - /// public: - /// LinearScanRegallocQuery(LiveIntervals &intervals) - /// : li(intervals) {} - /// - /// /// This is pretty slow and conservative, but since linear scan - /// /// allocation doesn't pre-compute interference information it's - /// /// the best we can do. Coalescers are always free to ignore this - /// /// and implement their own discovery strategy. See - /// /// SimpleRegisterCoalescing for an example. - /// void getInterferences(IntervalSet &interferences, - /// const LiveInterval &a) const { - /// for(LiveIntervals::const_iterator iv = li.begin(), - /// ivend = li.end(); - /// iv != ivend; - /// ++iv) { - /// if (interfere(a, iv->second)) { - /// interferences.insert(&iv->second); - /// } - /// } - /// } - /// - /// /// This is *really* slow and stupid. See above. - /// int getNumberOfInterferences(const LiveInterval &a) const { - /// IntervalSet intervals; - /// getInterferences(intervals, a); - /// return intervals.size(); - /// } - /// }; - /// - /// In the allocator: - /// - /// RegisterCoalescer &coalescer = getAnalysis<RegisterCoalescer>(); - /// - /// // We don't reset the coalescer so if it's already been run this - /// // takes almost no time. - /// LinearScanRegallocQuery ifd(*li_); - /// coalescer.coalesceFunction(fn, ifd); - /// - class RegallocQuery { - public: - typedef SmallPtrSet<const LiveInterval *, 8> IntervalSet; - - virtual ~RegallocQuery() {} - - /// Return whether two live ranges interfere. - virtual bool interfere(const LiveInterval &a, - const LiveInterval &b) const { - // A naive test - return a.overlaps(b); - } - - /// Return the set of intervals that interfere with this one. - virtual void getInterferences(IntervalSet &interferences, - const LiveInterval &a) const = 0; - - /// This can often be cheaper than actually returning the - /// interferences. - virtual int getNumberOfInterferences(const LiveInterval &a) const = 0; - - /// Make any data structure updates necessary to reflect - /// coalescing or other modifications. - virtual void updateDataForMerge(const LiveInterval &a, - const LiveInterval &b, - const MachineInstr ©) {} - - /// Allow the register allocator to communicate when it doesn't - /// want a copy coalesced. This may be due to assumptions made by - /// the allocator about various invariants and so this question is - /// a matter of legality, not performance. Performance decisions - /// about which copies to coalesce should be made by the - /// coalescer. - virtual bool isLegalToCoalesce(const MachineInstr &inst) const { - return true; - } - }; - - - /// CoalescerPair - A helper class for register coalescers. When deciding if - /// two registers can be coalesced, CoalescerPair can determine if a copy - /// instruction would become an identity copy after coalescing. - class CoalescerPair { - const TargetInstrInfo &tii_; - const TargetRegisterInfo &tri_; - - /// dstReg_ - The register that will be left after coalescing. It can be a - /// virtual or physical register. - unsigned dstReg_; - - /// srcReg_ - the virtual register that will be coalesced into dstReg. - unsigned srcReg_; - - /// subReg_ - The subregister index of srcReg in dstReg_. It is possible the - /// coalesce srcReg_ into a subreg of the larger dstReg_ when dstReg_ is a - /// virtual register. - unsigned subIdx_; - - /// partial_ - True when the original copy was a partial subregister copy. - bool partial_; - - /// crossClass_ - True when both regs are virtual, and newRC is constrained. - bool crossClass_; - - /// flipped_ - True when DstReg and SrcReg are reversed from the oriignal copy - /// instruction. - bool flipped_; - - /// newRC_ - The register class of the coalesced register, or NULL if dstReg_ - /// is a physreg. - const TargetRegisterClass *newRC_; - - /// compose - Compose subreg indices a and b, either may be 0. - unsigned compose(unsigned, unsigned) const; - - /// isMoveInstr - Return true if MI is a move or subreg instruction. - bool isMoveInstr(const MachineInstr *MI, unsigned &Src, unsigned &Dst, - unsigned &SrcSub, unsigned &DstSub) const; - - public: - CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri) - : tii_(tii), tri_(tri), dstReg_(0), srcReg_(0), subIdx_(0), - partial_(false), crossClass_(false), flipped_(false), newRC_(0) {} - - /// setRegisters - set registers to match the copy instruction MI. Return - /// false if MI is not a coalescable copy instruction. - bool setRegisters(const MachineInstr*); - - /// flip - Swap srcReg_ and dstReg_. Return false if swapping is impossible - /// because dstReg_ is a physical register, or subIdx_ is set. - bool flip(); - - /// isCoalescable - Return true if MI is a copy instruction that will become - /// an identity copy after coalescing. - bool isCoalescable(const MachineInstr*) const; - - /// isPhys - Return true if DstReg is a physical register. - bool isPhys() const { return !newRC_; } - - /// isPartial - Return true if the original copy instruction did not copy the - /// full register, but was a subreg operation. - bool isPartial() const { return partial_; } - - /// isCrossClass - Return true if DstReg is virtual and NewRC is a smaller register class than DstReg's. - bool isCrossClass() const { return crossClass_; } - - /// isFlipped - Return true when getSrcReg is the register being defined by - /// the original copy instruction. - bool isFlipped() const { return flipped_; } - - /// getDstReg - Return the register (virtual or physical) that will remain - /// after coalescing. - unsigned getDstReg() const { return dstReg_; } - - /// getSrcReg - Return the virtual register that will be coalesced away. - unsigned getSrcReg() const { return srcReg_; } - - /// getSubIdx - Return the subregister index in DstReg that SrcReg will be - /// coalesced into, or 0. - unsigned getSubIdx() const { return subIdx_; } - - /// getNewRC - Return the register class of the coalesced register. - const TargetRegisterClass *getNewRC() const { return newRC_; } - }; -} - -// Because of the way .a files work, we must force the SimpleRC -// implementation to be pulled in if the RegisterCoalescing header is -// included. Otherwise we run the risk of RegisterCoalescing being -// used, but the default implementation not being linked into the tool -// that uses it. -FORCE_DEFINING_FILE_TO_BE_LINKED(RegisterCoalescer) -FORCE_DEFINING_FILE_TO_BE_LINKED(SimpleRegisterCoalescing) - -#endif diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 0657664..1bbc6c5 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -34,7 +34,7 @@ namespace llvm { class ScheduleDAG; class SDNode; class TargetInstrInfo; - class TargetInstrDesc; + class MCInstrDesc; class TargetMachine; class TargetRegisterClass; template<class Graph> class GraphWriter; @@ -507,9 +507,9 @@ namespace llvm { virtual ~ScheduleDAG(); - /// getInstrDesc - Return the TargetInstrDesc of this SUnit. + /// getInstrDesc - Return the MCInstrDesc of this SUnit. /// Return NULL for SDNodes without a machine opcode. - const TargetInstrDesc *getInstrDesc(const SUnit *SU) const { + const MCInstrDesc *getInstrDesc(const SUnit *SU) const { if (SU->isInstr()) return &SU->getInstr()->getDesc(); return getNodeDesc(SU->getNode()); } @@ -579,8 +579,8 @@ namespace llvm { void EmitPhysRegCopy(SUnit *SU, DenseMap<SUnit*, unsigned> &VRBaseMap); private: - // Return the TargetInstrDesc of this SDNode or NULL. - const TargetInstrDesc *getNodeDesc(const SDNode *Node) const; + // Return the MCInstrDesc of this SDNode or NULL. + const MCInstrDesc *getNodeDesc(const SDNode *Node) const; }; class SUnitIterator : public std::iterator<std::forward_iterator_tag, diff --git a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h index 118df28..060e89a 100644 --- a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h +++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -25,7 +25,6 @@ namespace llvm { class InstrItineraryData; -class TargetInstrDesc; class ScheduleDAG; class SUnit; diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index ff59951..1afbb8a 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -387,6 +387,12 @@ public: /// std::string getAsString() const; + /// getAsCString - If this array is isCString(), then this method converts the + /// array (without the trailing null byte) to an std::string and returns it. + /// Otherwise, it asserts out. + /// + std::string getAsCString() const; + /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. This always returns false because zero arrays are always /// created as ConstantAggregateZero objects. diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 5efdcc9..dfd9246 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -65,6 +65,7 @@ void initializeArgPromotionPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeBasicCallGraphPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); +void initializeBlockFrequencyPass(PassRegistry&); void initializeBlockPlacementPass(PassRegistry&); void initializeBranchProbabilityInfoPass(PassRegistry&); void initializeBreakCriticalEdgesPass(PassRegistry&); @@ -176,7 +177,6 @@ void initializePostDomOnlyViewerPass(PassRegistry&); void initializePostDomPrinterPass(PassRegistry&); void initializePostDomViewerPass(PassRegistry&); void initializePostDominatorTreePass(PassRegistry&); -void initializePreAllocSplittingPass(PassRegistry&); void initializePreVerifierPass(PassRegistry&); void initializePrintDbgInfoPass(PassRegistry&); void initializePrintFunctionPassPass(PassRegistry&); @@ -197,7 +197,6 @@ void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); -void initializeRegisterCoalescerAnalysisGroup(PassRegistry&); void initializeRenderMachineFunctionPass(PassRegistry&); void initializeSCCPPass(PassRegistry&); void initializeSROA_DTPass(PassRegistry&); @@ -205,7 +204,7 @@ void initializeSROA_SSAUpPass(PassRegistry&); void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); void initializeSimpleInlinerPass(PassRegistry&); -void initializeSimpleRegisterCoalescingPass(PassRegistry&); +void initializeRegisterCoalescerPass(PassRegistry&); void initializeSimplifyLibCallsPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); diff --git a/include/llvm/InlineAsm.h b/include/llvm/InlineAsm.h index 0d86086..ed5bf8b 100644 --- a/include/llvm/InlineAsm.h +++ b/include/llvm/InlineAsm.h @@ -188,25 +188,32 @@ public: // in the backend. enum { + // Fixed operands on an INLINEASM SDNode. Op_InputChain = 0, Op_AsmString = 1, Op_MDNode = 2, Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack Op_FirstOperand = 4, + // Fixed operands on an INLINEASM MachineInstr. MIOp_AsmString = 0, MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack MIOp_FirstOperand = 2, + // Interpretation of the MIOp_ExtraInfo bit field. Extra_HasSideEffects = 1, Extra_IsAlignStack = 2, - - Kind_RegUse = 1, - Kind_RegDef = 2, - Kind_Imm = 3, - Kind_Mem = 4, - Kind_RegDefEarlyClobber = 6, - + + // Inline asm operands map to multiple SDNode / MachineInstr operands. + // The first operand is an immediate describing the asm operand, the low + // bits is the kind: + Kind_RegUse = 1, // Input register, "r". + Kind_RegDef = 2, // Output register, "=r". + Kind_RegDefEarlyClobber = 3, // Early-clobber output register, "=&r". + Kind_Clobber = 4, // Clobbered register, "~r". + Kind_Imm = 5, // Immediate. + Kind_Mem = 6, // Memory operand, "m". + Flag_MatchingOperand = 0x80000000 }; @@ -233,7 +240,10 @@ public: static bool isRegDefEarlyClobberKind(unsigned Flag) { return getKind(Flag) == Kind_RegDefEarlyClobber; } - + static bool isClobberKind(unsigned Flag) { + return getKind(Flag) == Kind_Clobber; + } + /// getNumOperandRegisters - Extract the number of registers field from the /// inline asm operand flag. static unsigned getNumOperandRegisters(unsigned Flag) { diff --git a/include/llvm/Target/TargetInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 6e20e8a..17d5fdc 100644 --- a/include/llvm/Target/TargetInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -1,4 +1,4 @@ -//===-- llvm/Target/TargetInstrDesc.h - Instruction Descriptors -*- C++ -*-===// +//===-- llvm/Mc/McInstrDesc.h - Instruction Descriptors -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,26 +7,23 @@ // //===----------------------------------------------------------------------===// // -// This file defines the TargetOperandInfo and TargetInstrDesc classes, which +// This file defines the MCOperandInfo and MCInstrDesc classes, which // are used to describe target instructions and their operands. // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_TARGETINSTRDESC_H -#define LLVM_TARGET_TARGETINSTRDESC_H +#ifndef LLVM_MC_MCINSTRDESC_H +#define LLVM_MC_MCINSTRDESC_H #include "llvm/Support/DataTypes.h" namespace llvm { -class TargetRegisterClass; -class TargetRegisterInfo; - //===----------------------------------------------------------------------===// // Machine Operand Flags and Description //===----------------------------------------------------------------------===// -namespace TOI { +namespace MCOI { // Operand constraints enum OperandConstraint { TIED_TO = 0, // Must be allocated the same register as. @@ -34,7 +31,7 @@ namespace TOI { }; /// OperandFlags - These are flags set on operands, but should be considered - /// private, all access should go through the TargetOperandInfo accessors. + /// private, all access should go through the MCOperandInfo accessors. /// See the accessors for a description of what these are. enum OperandFlags { LookupPtrRegClass = 0, @@ -43,21 +40,18 @@ namespace TOI { }; } -/// TargetOperandInfo - This holds information about one operand of a machine +/// MCOperandInfo - This holds information about one operand of a machine /// instruction, indicating the register class for register operands, etc. /// -class TargetOperandInfo { +class MCOperandInfo { public: /// RegClass - This specifies the register class enumeration of the operand /// if the operand is a register. If isLookupPtrRegClass is set, then this is /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to /// get a dynamic register class. - /// - /// NOTE: This member should be considered to be private, all access should go - /// through "getRegClass(TRI)" below. short RegClass; - /// Flags - These are flags from the TOI::OperandFlags enum. + /// Flags - These are flags from the MCOI::OperandFlags enum. unsigned short Flags; /// Lower 16 bits are used to specify which constraints are set. The higher 16 @@ -65,23 +59,17 @@ public: unsigned Constraints; /// Currently no other information. - /// getRegClass - Get the register class for the operand, handling resolution - /// of "symbolic" pointer register classes etc. If this is not a register - /// operand, this returns null. - const TargetRegisterClass *getRegClass(const TargetRegisterInfo *TRI) const; - - /// isLookupPtrRegClass - Set if this operand is a pointer value and it /// requires a callback to look up its register class. - bool isLookupPtrRegClass() const { return Flags&(1 <<TOI::LookupPtrRegClass);} + bool isLookupPtrRegClass() const { return Flags&(1 <<MCOI::LookupPtrRegClass);} /// isPredicate - Set if this is one of the operands that made up of /// the predicate operand that controls an isPredicable() instruction. - bool isPredicate() const { return Flags & (1 << TOI::Predicate); } + bool isPredicate() const { return Flags & (1 << MCOI::Predicate); } /// isOptionalDef - Set if this operand is a optional def. /// - bool isOptionalDef() const { return Flags & (1 << TOI::OptionalDef); } + bool isOptionalDef() const { return Flags & (1 << MCOI::OptionalDef); } }; @@ -89,11 +77,11 @@ public: // Machine Instruction Flags and Description //===----------------------------------------------------------------------===// -/// TargetInstrDesc flags - These should be considered private to the -/// implementation of the TargetInstrDesc class. Clients should use the -/// predicate methods on TargetInstrDesc, not use these directly. These -/// all correspond to bitfields in the TargetInstrDesc::Flags field. -namespace TID { +/// MCInstrDesc flags - These should be considered private to the +/// implementation of the MCInstrDesc class. Clients should use the predicate +/// methods on MCInstrDesc, not use these directly. These all correspond to +/// bitfields in the MCInstrDesc::Flags field. +namespace MCID { enum { Variadic = 0, HasOptionalDef, @@ -123,12 +111,12 @@ namespace TID { }; } -/// TargetInstrDesc - Describe properties that are true of each -/// instruction in the target description file. This captures information about -/// side effects, register use and many other things. There is one instance of -/// this struct for each target instruction class, and the MachineInstr class -/// points to this struct directly to describe itself. -class TargetInstrDesc { +/// MCInstrDesc - Describe properties that are true of each instruction in the +/// target description file. This captures information about side effects, +/// register use and many other things. There is one instance of this struct +/// for each target instruction class, and the MachineInstr class points to +/// this struct directly to describe itself. +class MCInstrDesc { public: unsigned short Opcode; // The opcode number unsigned short NumOperands; // Num of args (may be more if variable_ops) @@ -139,13 +127,12 @@ public: uint64_t TSFlags; // Target Specific Flag values const unsigned *ImplicitUses; // Registers implicitly read by this instr const unsigned *ImplicitDefs; // Registers implicitly defined by this instr - const TargetRegisterClass **RCBarriers; // Reg classes completely "clobbered" - const TargetOperandInfo *OpInfo; // 'NumOperands' entries about operands + const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands /// getOperandConstraint - Returns the value of the specific constraint if /// it is set. Returns -1 if it is not set. int getOperandConstraint(unsigned OpNum, - TOI::OperandConstraint Constraint) const { + MCOI::OperandConstraint Constraint) const { if (OpNum < NumOperands && (OpInfo[OpNum].Constraints & (1 << Constraint))) { unsigned Pos = 16 + Constraint * 4; @@ -154,12 +141,6 @@ public: return -1; } - /// getRegClass - Returns the register class constraint for OpNum, or NULL. - const TargetRegisterClass *getRegClass(unsigned OpNum, - const TargetRegisterInfo *TRI) const { - return OpNum < NumOperands ? OpInfo[OpNum].getRegClass(TRI) : 0; - } - /// getOpcode - Return the opcode number for this descriptor. unsigned getOpcode() const { return Opcode; @@ -193,13 +174,13 @@ public: /// operands but before the implicit definitions and uses (if any are /// present). bool isVariadic() const { - return Flags & (1 << TID::Variadic); + return Flags & (1 << MCID::Variadic); } /// hasOptionalDef - Set if this instruction has an optional definition, e.g. /// ARM instructions which can set condition code if 's' bit is set. bool hasOptionalDef() const { - return Flags & (1 << TID::HasOptionalDef); + return Flags & (1 << MCID::HasOptionalDef); } /// getImplicitUses - Return a list of registers that are potentially @@ -214,7 +195,7 @@ public: const unsigned *getImplicitUses() const { return ImplicitUses; } - + /// getNumImplicitUses - Return the number of implicit uses this instruction /// has. unsigned getNumImplicitUses() const { @@ -223,8 +204,7 @@ public: for (; ImplicitUses[i]; ++i) /*empty*/; return i; } - - + /// getImplicitDefs - Return a list of registers that are potentially /// written by any instance of this machine instruction. For example, on X86, /// many instructions implicitly set the flags register. In this case, they @@ -266,17 +246,6 @@ public: return false; } - /// getRegClassBarriers - Return a list of register classes that are - /// completely clobbered by this machine instruction. For example, on X86 - /// the call instructions will completely clobber all the registers in the - /// fp stack and XMM classes. - /// - /// This method returns null if the instruction doesn't completely clobber - /// any register class. - const TargetRegisterClass **getRegClassBarriers() const { - return RCBarriers; - } - /// getSchedClass - Return the scheduling class for this instruction. The /// scheduling class is an index into the InstrItineraryData table. This /// returns zero if there is no known scheduling information for the @@ -287,18 +256,18 @@ public: } bool isReturn() const { - return Flags & (1 << TID::Return); + return Flags & (1 << MCID::Return); } bool isCall() const { - return Flags & (1 << TID::Call); + return Flags & (1 << MCID::Call); } /// isBarrier - Returns true if the specified instruction stops control flow /// from executing the instruction immediately following it. Examples include /// unconditional branches and return instructions. bool isBarrier() const { - return Flags & (1 << TID::Barrier); + return Flags & (1 << MCID::Barrier); } /// isTerminator - Returns true if this instruction part of the terminator for @@ -308,7 +277,7 @@ public: /// Various passes use this to insert code into the bottom of a basic block, /// but before control flow occurs. bool isTerminator() const { - return Flags & (1 << TID::Terminator); + return Flags & (1 << MCID::Terminator); } /// isBranch - Returns true if this is a conditional, unconditional, or @@ -316,13 +285,13 @@ public: /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to /// get more information. bool isBranch() const { - return Flags & (1 << TID::Branch); + return Flags & (1 << MCID::Branch); } /// isIndirectBranch - Return true if this is an indirect branch, such as a /// branch through a register. bool isIndirectBranch() const { - return Flags & (1 << TID::IndirectBranch); + return Flags & (1 << MCID::IndirectBranch); } /// isConditionalBranch - Return true if this is a branch which may fall @@ -346,37 +315,37 @@ public: /// values. There are various methods in TargetInstrInfo that can be used to /// control and modify the predicate in this instruction. bool isPredicable() const { - return Flags & (1 << TID::Predicable); + return Flags & (1 << MCID::Predicable); } /// isCompare - Return true if this instruction is a comparison. bool isCompare() const { - return Flags & (1 << TID::Compare); + return Flags & (1 << MCID::Compare); } /// isMoveImmediate - Return true if this instruction is a move immediate /// (including conditional moves) instruction. bool isMoveImmediate() const { - return Flags & (1 << TID::MoveImm); + return Flags & (1 << MCID::MoveImm); } /// isBitcast - Return true if this instruction is a bitcast instruction. /// bool isBitcast() const { - return Flags & (1 << TID::Bitcast); + return Flags & (1 << MCID::Bitcast); } /// isNotDuplicable - Return true if this instruction cannot be safely /// duplicated. For example, if the instruction has a unique labels attached /// to it, duplicating it would cause multiple definition errors. bool isNotDuplicable() const { - return Flags & (1 << TID::NotDuplicable); + return Flags & (1 << MCID::NotDuplicable); } /// hasDelaySlot - Returns true if the specified instruction has a delay slot /// which must be filled by the code generator. bool hasDelaySlot() const { - return Flags & (1 << TID::DelaySlot); + return Flags & (1 << MCID::DelaySlot); } /// canFoldAsLoad - Return true for instructions that can be folded as @@ -388,7 +357,7 @@ public: /// This should only be set on instructions that return a value in their /// only virtual register definition. bool canFoldAsLoad() const { - return Flags & (1 << TID::FoldableAsLoad); + return Flags & (1 << MCID::FoldableAsLoad); } //===--------------------------------------------------------------------===// @@ -399,7 +368,7 @@ public: /// Instructions with this flag set are not necessarily simple load /// instructions, they may load a value and modify it, for example. bool mayLoad() const { - return Flags & (1 << TID::MayLoad); + return Flags & (1 << MCID::MayLoad); } @@ -408,7 +377,7 @@ public: /// instructions, they may store a modified value based on their operands, or /// may not actually modify anything, for example. bool mayStore() const { - return Flags & (1 << TID::MayStore); + return Flags & (1 << MCID::MayStore); } /// hasUnmodeledSideEffects - Return true if this instruction has side @@ -425,7 +394,7 @@ public: /// LLVM, etc. /// bool hasUnmodeledSideEffects() const { - return Flags & (1 << TID::UnmodeledSideEffects); + return Flags & (1 << MCID::UnmodeledSideEffects); } //===--------------------------------------------------------------------===// @@ -443,7 +412,7 @@ public: /// Also note that some instructions require non-trivial modification to /// commute them. bool isCommutable() const { - return Flags & (1 << TID::Commutable); + return Flags & (1 << MCID::Commutable); } /// isConvertibleTo3Addr - Return true if this is a 2-address instruction @@ -461,7 +430,7 @@ public: /// instruction (e.g. shl reg, 4 on x86). /// bool isConvertibleTo3Addr() const { - return Flags & (1 << TID::ConvertibleTo3Addr); + return Flags & (1 << MCID::ConvertibleTo3Addr); } /// usesCustomInsertionHook - Return true if this instruction requires @@ -473,7 +442,7 @@ public: /// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method /// is used to insert this into the MachineBasicBlock. bool usesCustomInsertionHook() const { - return Flags & (1 << TID::UsesCustomInserter); + return Flags & (1 << MCID::UsesCustomInserter); } /// isRematerializable - Returns true if this instruction is a candidate for @@ -481,7 +450,7 @@ public: /// flag is set, the isReallyTriviallyReMaterializable() method is called to /// verify the instruction is really rematable. bool isRematerializable() const { - return Flags & (1 << TID::Rematerializable); + return Flags & (1 << MCID::Rematerializable); } /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or @@ -491,7 +460,7 @@ public: /// more than moving the instruction into the appropriate register. Note, we /// are not marking copies from and to the same register class with this flag. bool isAsCheapAsAMove() const { - return Flags & (1 << TID::CheapAsAMove); + return Flags & (1 << MCID::CheapAsAMove); } /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands @@ -501,7 +470,7 @@ public: /// Post-register allocation passes should not attempt to change allocations /// for sources of instructions with this flag. bool hasExtraSrcRegAllocReq() const { - return Flags & (1 << TID::ExtraSrcRegAllocReq); + return Flags & (1 << MCID::ExtraSrcRegAllocReq); } /// hasExtraDefRegAllocReq - Returns true if this instruction def operands @@ -511,7 +480,7 @@ public: /// Post-register allocation passes should not attempt to change allocations /// for definitions of instructions with this flag. bool hasExtraDefRegAllocReq() const { - return Flags & (1 << TID::ExtraDefRegAllocReq); + return Flags & (1 << MCID::ExtraDefRegAllocReq); } }; diff --git a/include/llvm/MC/MCInstrInfo.h b/include/llvm/MC/MCInstrInfo.h new file mode 100644 index 0000000..a63e5fa --- /dev/null +++ b/include/llvm/MC/MCInstrInfo.h @@ -0,0 +1,51 @@ +//===-- llvm/MC/MCInstrInfo.h - Target Instruction Info ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the target machine instruction set. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTRINFO_H +#define LLVM_MC_MCINSTRINFO_H + +#include "llvm/MC/MCInstrDesc.h" +#include <cassert> + +namespace llvm { + +//--------------------------------------------------------------------------- +/// +/// MCInstrInfo - Interface to description of machine instruction set +/// +class MCInstrInfo { + const MCInstrDesc *Desc; // Raw array to allow static init'n + unsigned NumOpcodes; // Number of entries in the desc array + +public: + /// InitMCInstrInfo - Initialize MCInstrInfo, called by TableGen + /// auto-generated routines. *DO NOT USE*. + void InitMCInstrInfo(const MCInstrDesc *D, unsigned NO) { + Desc = D; + NumOpcodes = NO; + } + + unsigned getNumOpcodes() const { return NumOpcodes; } + + /// get - Return the machine instruction descriptor that corresponds to the + /// specified instruction opcode. + /// + const MCInstrDesc &get(unsigned Opcode) const { + assert(Opcode < NumOpcodes && "Invalid opcode!"); + return Desc[Opcode]; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index 6011402..e942892 100644 --- a/include/llvm/Target/TargetInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -1,4 +1,4 @@ -//===-- llvm/Target/TargetInstrItineraries.h - Scheduling -------*- C++ -*-===// +//===-- llvm/MC/MCInstrItineraries.h - Scheduling ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_TARGETINSTRITINERARIES_H -#define LLVM_TARGET_TARGETINSTRITINERARIES_H +#ifndef LLVM_MC_MCINSTRITINERARIES_H +#define LLVM_MC_MCINSTRITINERARIES_H #include <algorithm> diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index ec51031..9bb598f 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -10,11 +10,20 @@ #ifndef LLVM_MC_MCMACHOBJECTWRITER_H #define LLVM_MC_MCMACHOBJECTWRITER_H +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/Object/MachOFormat.h" #include "llvm/Support/DataTypes.h" +#include <vector> namespace llvm { +class MCSectionData; +class MachObjectWriter; + class MCMachObjectTargetWriter { const unsigned Is64Bit : 1; const uint32_t CPUType; @@ -48,8 +57,191 @@ public: } /// @} + + /// @name API + /// @{ + + virtual void RecordRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) = 0; + + /// @} }; +class MachObjectWriter : public MCObjectWriter { + /// MachSymbolData - Helper struct for containing some precomputed information + /// on symbols. + struct MachSymbolData { + MCSymbolData *SymbolData; + uint64_t StringIndex; + uint8_t SectionIndex; + + // Support lexicographic sorting. + bool operator<(const MachSymbolData &RHS) const; + }; + + /// The target specific Mach-O writer instance. + llvm::OwningPtr<MCMachObjectTargetWriter> TargetObjectWriter; + + /// @name Relocation Data + /// @{ + + llvm::DenseMap<const MCSectionData*, + std::vector<object::macho::RelocationEntry> > Relocations; + llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase; + + /// @} + /// @name Symbol Table Data + /// @{ + + SmallString<256> StringTable; + std::vector<MachSymbolData> LocalSymbolData; + std::vector<MachSymbolData> ExternalSymbolData; + std::vector<MachSymbolData> UndefinedSymbolData; + + /// @} + +public: + MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS, + bool _IsLittleEndian) + : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) { + } + + /// @name Utility Methods + /// @{ + + bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); + + SectionAddrMap SectionAddress; + + SectionAddrMap &getSectionAddressMap() { return SectionAddress; } + + uint64_t getSectionAddress(const MCSectionData* SD) const { + return SectionAddress.lookup(SD); + } + uint64_t getSymbolAddress(const MCSymbolData* SD, + const MCAsmLayout &Layout) const; + + uint64_t getFragmentAddress(const MCFragment *Fragment, + const MCAsmLayout &Layout) const; + + uint64_t getPaddingSize(const MCSectionData *SD, + const MCAsmLayout &Layout) const; + + bool doesSymbolRequireExternRelocation(const MCSymbolData *SD); + + /// @} + + /// @name Target Writer Proxy Accessors + /// @{ + + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + bool isARM() const { + uint32_t CPUType = TargetObjectWriter->getCPUType() & + ~object::mach::CTFM_ArchMask; + return CPUType == object::mach::CTM_ARM; + } + + /// @} + + void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize, + bool SubsectionsViaSymbols); + + /// WriteSegmentLoadCommand - Write a segment load command. + /// + /// \arg NumSections - The number of sections in this segment. + /// \arg SectionDataSize - The total size of the sections. + void WriteSegmentLoadCommand(unsigned NumSections, + uint64_t VMSize, + uint64_t SectionDataStartOffset, + uint64_t SectionDataSize); + + void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCSectionData &SD, uint64_t FileOffset, + uint64_t RelocationsStart, unsigned NumRelocations); + + void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, + uint32_t StringTableOffset, + uint32_t StringTableSize); + + void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, + uint32_t NumLocalSymbols, + uint32_t FirstExternalSymbol, + uint32_t NumExternalSymbols, + uint32_t FirstUndefinedSymbol, + uint32_t NumUndefinedSymbols, + uint32_t IndirectSymbolOffset, + uint32_t NumIndirectSymbols); + + void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout); + + // FIXME: We really need to improve the relocation validation. Basically, we + // want to implement a separate computation which evaluates the relocation + // entry as the linker would, and verifies that the resultant fixup value is + // exactly what the encoder wanted. This will catch several classes of + // problems: + // + // - Relocation entry bugs, the two algorithms are unlikely to have the same + // exact bug. + // + // - Relaxation issues, where we forget to relax something. + // + // - Input errors, where something cannot be correctly encoded. 'as' allows + // these through in many cases. + + void addRelocation(const MCSectionData *SD, + object::macho::RelocationEntry &MRE) { + Relocations[SD].push_back(MRE); + } + + void RecordScatteredRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue); + + void RecordTLVPRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue); + + void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue); + + void BindIndirectSymbols(MCAssembler &Asm); + + /// ComputeSymbolTable - Compute the symbol table data + /// + /// \param StringTable [out] - The string table data. + /// \param StringIndexMap [out] - Map from symbol names to offsets in the + /// string table. + void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, + std::vector<MachSymbolData> &LocalSymbolData, + std::vector<MachSymbolData> &ExternalSymbolData, + std::vector<MachSymbolData> &UndefinedSymbolData); + + void computeSectionAddresses(const MCAssembler &Asm, + const MCAsmLayout &Layout); + + void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); + + virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); +}; + + /// \brief Construct a new Mach-O writer instance. /// /// This routine takes ownership of the target writer subclass. diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h new file mode 100644 index 0000000..caf98bb --- /dev/null +++ b/include/llvm/MC/MCRegisterInfo.h @@ -0,0 +1,129 @@ +//=== MC/MCRegisterInfo.h - Target Register Description ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes an abstract interface used to get information about a +// target machines register file. This information is used for a variety of +// purposed, especially register allocation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCREGISTERINFO_H +#define LLVM_MC_MCREGISTERINFO_H + +#include <cassert> + +namespace llvm { + +/// MCRegisterDesc - This record contains all of the information known about +/// a particular register. The Overlaps field contains a pointer to a zero +/// terminated array of registers that this register aliases, starting with +/// itself. This is needed for architectures like X86 which have AL alias AX +/// alias EAX. The SubRegs field is a zero terminated array of registers that +/// are sub-registers of the specific register, e.g. AL, AH are sub-registers of +/// AX. The SuperRegs field is a zero terminated array of registers that are +/// super-registers of the specific register, e.g. RAX, EAX, are super-registers +/// of AX. +/// +struct MCRegisterDesc { + const char *Name; // Printable name for the reg (for debugging) + const unsigned *Overlaps; // Overlapping registers, described above + const unsigned *SubRegs; // Sub-register set, described above + const unsigned *SuperRegs; // Super-register set, described above +}; + +/// MCRegisterInfo base class - We assume that the target defines a static +/// array of MCRegisterDesc objects that represent all of the machine +/// registers that the target has. As such, we simply have to track a pointer +/// to this array so that we can turn register number into a register +/// descriptor. +/// +/// Note this class is designed to be a base class of TargetRegisterInfo, which +/// is the interface used by codegen. However, specific targets *should never* +/// specialize this class. MCRegisterInfo should only contain getters to access +/// TableGen generated physical register data. It must not be extended with +/// virtual methods. +/// +class MCRegisterInfo { +private: + const MCRegisterDesc *Desc; // Pointer to the descriptor array + unsigned NumRegs; // Number of entries in the array + +public: + /// InitMCRegisterInfo - Initialize MCRegisterInfo, called by TableGen + /// auto-generated routines. *DO NOT USE*. + void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR) { + Desc = D; + NumRegs = NR; + } + + const MCRegisterDesc &operator[](unsigned RegNo) const { + assert(RegNo < NumRegs && + "Attempting to access record for invalid register number!"); + return Desc[RegNo]; + } + + /// Provide a get method, equivalent to [], but more useful if we have a + /// pointer to this object. + /// + const MCRegisterDesc &get(unsigned RegNo) const { + return operator[](RegNo); + } + + /// getAliasSet - Return the set of registers aliased by the specified + /// register, or a null list of there are none. The list returned is zero + /// terminated. + /// + const unsigned *getAliasSet(unsigned RegNo) const { + // The Overlaps set always begins with Reg itself. + return get(RegNo).Overlaps + 1; + } + + /// getOverlaps - Return a list of registers that overlap Reg, including + /// itself. This is the same as the alias set except Reg is included in the + /// list. + /// These are exactly the registers in { x | regsOverlap(x, Reg) }. + /// + const unsigned *getOverlaps(unsigned RegNo) const { + return get(RegNo).Overlaps; + } + + /// getSubRegisters - Return the list of registers that are sub-registers of + /// the specified register, or a null list of there are none. The list + /// returned is zero terminated and sorted according to super-sub register + /// relations. e.g. X86::RAX's sub-register list is EAX, AX, AL, AH. + /// + const unsigned *getSubRegisters(unsigned RegNo) const { + return get(RegNo).SubRegs; + } + + /// getSuperRegisters - Return the list of registers that are super-registers + /// of the specified register, or a null list of there are none. The list + /// returned is zero terminated and sorted according to super-sub register + /// relations. e.g. X86::AL's super-register list is AX, EAX, RAX. + /// + const unsigned *getSuperRegisters(unsigned RegNo) const { + return get(RegNo).SuperRegs; + } + + /// getName - Return the human-readable symbolic target-specific name for the + /// specified physical register. + const char *getName(unsigned RegNo) const { + return get(RegNo).Name; + } + + /// getNumRegs - Return the number of registers this target has (useful for + /// sizing arrays holding per register information) + unsigned getNumRegs() const { + return NumRegs; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index 4213d9b..fccff03 100644 --- a/include/llvm/Target/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -1,4 +1,4 @@ -//===-- llvm/Target/SubtargetFeature.h - CPU characteristics ----*- C++ -*-===// +//===-- llvm/MC/SubtargetFeature.h - CPU characteristics --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,17 +15,16 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_SUBTARGETFEATURE_H -#define LLVM_TARGET_SUBTARGETFEATURE_H +#ifndef LLVM_MC_SUBTARGETFEATURE_H +#define LLVM_MC_SUBTARGETFEATURE_H -#include <string> #include <vector> -#include <cstring> #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" namespace llvm { class raw_ostream; + class StringRef; //===----------------------------------------------------------------------===// /// @@ -75,32 +74,24 @@ struct SubtargetInfoKV { class SubtargetFeatures { std::vector<std::string> Features; // Subtarget features as a vector public: - explicit SubtargetFeatures(const std::string &Initial = std::string()); + explicit SubtargetFeatures(const StringRef Initial = ""); /// Features string accessors. std::string getString() const; - void setString(const std::string &Initial); - - /// Set the CPU string. Replaces previous setting. Setting to "" clears CPU. - void setCPU(const std::string &String); - - /// Setting CPU string only if no string is set. - void setCPUIfNone(const std::string &String); - - /// Returns current CPU string. - const std::string & getCPU() const; /// Adding Features. - void AddFeature(const std::string &String, bool IsEnabled = true); + void AddFeature(const StringRef String, bool IsEnabled = true); - /// Get feature bits. - uint64_t getBits(const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize); + /// Get feature bits of a CPU. + uint64_t getFeatureBits(const StringRef CPU, + const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize); - /// Get info pointer - void *getInfo(const SubtargetInfoKV *Table, size_t TableSize); + /// Get scheduling itinerary of a CPU. + void *getItinerary(const StringRef CPU, + const SubtargetInfoKV *Table, size_t TableSize); /// Print feature string. void print(raw_ostream &OS) const; @@ -110,8 +101,7 @@ public: /// Retrieve a formatted string of the default features for the specified /// target triple. - void getDefaultSubtargetFeatures(const std::string &CPU, - const Triple& Triple); + void getDefaultSubtargetFeatures(const Triple& Triple); }; } // End namespace llvm diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h new file mode 100644 index 0000000..cd092fd --- /dev/null +++ b/include/llvm/Object/Binary.h @@ -0,0 +1,67 @@ +//===- Binary.h - A generic binary file -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Binary class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_BINARY_H +#define LLVM_OBJECT_BINARY_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Object/Error.h" + +namespace llvm { + +class MemoryBuffer; +class StringRef; + +namespace object { + +class Binary { +private: + Binary(); // = delete + Binary(const Binary &other); // = delete + + unsigned int TypeID; + +protected: + MemoryBuffer *Data; + + Binary(unsigned int Type, MemoryBuffer *Source); + + enum { + isArchive, + + // Object and children. + isObject, + isCOFF, + isELF, + isMachO, + lastObject + }; + +public: + virtual ~Binary(); + + StringRef getData() const; + StringRef getFileName() const; + + // Cast methods. + unsigned int getType() const { return TypeID; } + static inline bool classof(const Binary *v) { return true; } +}; + +error_code createBinary(MemoryBuffer *Source, OwningPtr<Binary> &Result); +error_code createBinary(StringRef Path, OwningPtr<Binary> &Result); + +} +} + +#endif diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h new file mode 100644 index 0000000..6a5e0d9 --- /dev/null +++ b/include/llvm/Object/COFF.h @@ -0,0 +1,115 @@ +//===- COFF.h - COFF object file implementation -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the COFFObjectFile class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_COFF_H +#define LLVM_OBJECT_COFF_H + +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/COFF.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace object { + +struct coff_file_header { + support::ulittle16_t Machine; + support::ulittle16_t NumberOfSections; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t PointerToSymbolTable; + support::ulittle32_t NumberOfSymbols; + support::ulittle16_t SizeOfOptionalHeader; + support::ulittle16_t Characteristics; +}; + +struct coff_symbol { + struct StringTableOffset { + support::ulittle32_t Zeroes; + support::ulittle32_t Offset; + }; + + union { + char ShortName[8]; + StringTableOffset Offset; + } Name; + + support::ulittle32_t Value; + support::little16_t SectionNumber; + + struct { + support::ulittle8_t BaseType; + support::ulittle8_t ComplexType; + } Type; + + support::ulittle8_t StorageClass; + support::ulittle8_t NumberOfAuxSymbols; +}; + +struct coff_section { + char Name[8]; + support::ulittle32_t VirtualSize; + support::ulittle32_t VirtualAddress; + support::ulittle32_t SizeOfRawData; + support::ulittle32_t PointerToRawData; + support::ulittle32_t PointerToRelocations; + support::ulittle32_t PointerToLinenumbers; + support::ulittle16_t NumberOfRelocations; + support::ulittle16_t NumberOfLinenumbers; + support::ulittle32_t Characteristics; +}; + +class COFFObjectFile : public ObjectFile { +private: + const coff_file_header *Header; + const coff_section *SectionTable; + const coff_symbol *SymbolTable; + const char *StringTable; + uint32_t StringTableSize; + + error_code getSection(int32_t index, + const coff_section *&Res) const; + error_code getString(uint32_t offset, StringRef &Res) const; + + const coff_symbol *toSymb(DataRefImpl Symb) const; + const coff_section *toSec(DataRefImpl Sec) const; + +protected: + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; + +public: + COFFObjectFile(MemoryBuffer *Object, error_code &ec); + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; +}; + +} +} + +#endif diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h new file mode 100644 index 0000000..fbaf71c --- /dev/null +++ b/include/llvm/Object/Error.h @@ -0,0 +1,50 @@ +//===- Error.h - system_error extensions for Object -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This declares a new error_category for the Object library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ERROR_H +#define LLVM_OBJECT_ERROR_H + +#include "llvm/Support/system_error.h" + +namespace llvm { +namespace object { + +const error_category &object_category(); + +struct object_error { +enum _ { + success = 0, + invalid_file_type, + parse_failed, + unexpected_eof +}; + _ v_; + + object_error(_ v) : v_(v) {} + explicit object_error(int v) : v_(_(v)) {} + operator int() const {return v_;} +}; + +inline error_code make_error_code(object_error e) { + return error_code(static_cast<int>(e), object_category()); +} + +} // end namespace object. + +template <> struct is_error_code_enum<object::object_error> : true_type { }; + +template <> struct is_error_code_enum<object::object_error::_> : true_type { }; + +} // end namespace llvm. + +#endif diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index eee9d44..f083d3c 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -14,15 +14,14 @@ #ifndef LLVM_OBJECT_OBJECT_FILE_H #define LLVM_OBJECT_OBJECT_FILE_H +#include "llvm/Object/Binary.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" #include <cstring> namespace llvm { - -class MemoryBuffer; -class StringRef; - namespace object { class ObjectFile; @@ -31,7 +30,7 @@ union DataRefImpl { struct { uint32_t a, b; } d; - intptr_t p; + uintptr_t p; }; static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { @@ -40,6 +39,19 @@ static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; } +class RelocationRef { + DataRefImpl RelocationPimpl; + const ObjectFile *OwningObject; + +public: + RelocationRef() : OwningObject(NULL) { std::memset(&RelocationPimpl, 0, sizeof(RelocationPimpl)); } + RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); + + bool operator==(const RelocationRef &Other) const; + + error_code getNext(RelocationRef &Result); +}; + /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. class SymbolRef { @@ -47,23 +59,24 @@ class SymbolRef { const ObjectFile *OwningObject; public: + SymbolRef() : OwningObject(NULL) { std::memset(&SymbolPimpl, 0, sizeof(SymbolPimpl)); } SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); bool operator==(const SymbolRef &Other) const; - SymbolRef getNext() const; + error_code getNext(SymbolRef &Result) const; - StringRef getName() const; - uint64_t getAddress() const; - uint64_t getSize() const; + error_code getName(StringRef &Result) const; + error_code getAddress(uint64_t &Result) const; + error_code getSize(uint64_t &Result) const; /// Returns the ascii char that should be displayed in a symbol table dump via /// nm for this symbol. - char getNMTypeChar() const; + error_code getNMTypeChar(char &Result) const; /// Returns true for symbols that are internal to the object file format such /// as section symbols. - bool isInternal() const; + error_code isInternal(bool &Result) const; }; /// SectionRef - This is a value type class that represents a single section in @@ -73,19 +86,20 @@ class SectionRef { const ObjectFile *OwningObject; public: + SectionRef() : OwningObject(NULL) { std::memset(&SectionPimpl, 0, sizeof(SectionPimpl)); } SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); bool operator==(const SectionRef &Other) const; - SectionRef getNext() const; + error_code getNext(SectionRef &Result) const; - StringRef getName() const; - uint64_t getAddress() const; - uint64_t getSize() const; - StringRef getContents() const; + error_code getName(StringRef &Result) const; + error_code getAddress(uint64_t &Result) const; + error_code getSize(uint64_t &Result) const; + error_code getContents(StringRef &Result) const; // FIXME: Move to the normalization layer when it's created. - bool isText() const; + error_code isText(bool &Result) const; }; const uint64_t UnknownAddressOrSize = ~0ULL; @@ -93,38 +107,42 @@ const uint64_t UnknownAddressOrSize = ~0ULL; /// ObjectFile - This class is the base class for all object file types. /// Concrete instances of this object are created by createObjectFile, which /// figure out which type to create. -class ObjectFile { +class ObjectFile : public Binary { private: ObjectFile(); // = delete ObjectFile(const ObjectFile &other); // = delete protected: - MemoryBuffer *MapFile; - const uint8_t *base; + ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec); - ObjectFile(MemoryBuffer *Object); + const uint8_t *base() const { + return reinterpret_cast<const uint8_t *>(Data->getBufferStart()); + } // These functions are for SymbolRef to call internally. The main goal of // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol // entry in the memory mapped object file. SymbolPimpl cannot contain any // virtual functions because then it could not point into the memory mapped // file. + // + // Implementations assume that the DataRefImpl is valid and has not been + // modified externally. It's UB otherwise. friend class SymbolRef; - virtual SymbolRef getSymbolNext(DataRefImpl Symb) const = 0; - virtual StringRef getSymbolName(DataRefImpl Symb) const = 0; - virtual uint64_t getSymbolAddress(DataRefImpl Symb) const = 0; - virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; - virtual char getSymbolNMTypeChar(DataRefImpl Symb) const = 0; - virtual bool isSymbolInternal(DataRefImpl Symb) const = 0; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const = 0; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const =0; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const = 0; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const = 0; // Same as above for SectionRef. friend class SectionRef; - virtual SectionRef getSectionNext(DataRefImpl Sec) const = 0; - virtual StringRef getSectionName(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; - virtual StringRef getSectionContents(DataRefImpl Sec) const = 0; - virtual bool isSectionText(DataRefImpl Sec) const = 0; + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const = 0; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const =0; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const = 0; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res)const=0; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; public: @@ -147,8 +165,12 @@ public: return !(*this == other); } - content_iterator& operator++() { // Preincrement - Current = Current.getNext(); + content_iterator& increment(error_code &err) { + content_type next; + if (error_code ec = Current.getNext(next)) + err = ec; + else + Current = next; return *this; } }; @@ -156,8 +178,6 @@ public: typedef content_iterator<SymbolRef> symbol_iterator; typedef content_iterator<SectionRef> section_iterator; - virtual ~ObjectFile(); - virtual symbol_iterator begin_symbols() const = 0; virtual symbol_iterator end_symbols() const = 0; @@ -171,8 +191,6 @@ public: virtual StringRef getFileFormatName() const = 0; virtual /* Triple::ArchType */ unsigned getArch() const = 0; - StringRef getFilename() const; - /// @returns Pointer to ObjectFile subclass to handle this type of object. /// @param ObjectPath The path to the object file. ObjectPath.isObject must /// return true. @@ -180,12 +198,16 @@ public: static ObjectFile *createObjectFile(StringRef ObjectPath); static ObjectFile *createObjectFile(MemoryBuffer *Object); -private: + static inline bool classof(const Binary *v) { + return v->getType() >= isObject && + v->getType() < lastObject; + } + static inline bool classof(const ObjectFile *v) { return true; } + +public: static ObjectFile *createCOFFObjectFile(MemoryBuffer *Object); static ObjectFile *createELFObjectFile(MemoryBuffer *Object); static ObjectFile *createMachOObjectFile(MemoryBuffer *Object); - static ObjectFile *createArchiveObjectFile(MemoryBuffer *Object); - static ObjectFile *createLibObjectFile(MemoryBuffer *Object); }; // Inline function definitions. @@ -197,28 +219,28 @@ inline bool SymbolRef::operator==(const SymbolRef &Other) const { return SymbolPimpl == Other.SymbolPimpl; } -inline SymbolRef SymbolRef::getNext() const { - return OwningObject->getSymbolNext(SymbolPimpl); +inline error_code SymbolRef::getNext(SymbolRef &Result) const { + return OwningObject->getSymbolNext(SymbolPimpl, Result); } -inline StringRef SymbolRef::getName() const { - return OwningObject->getSymbolName(SymbolPimpl); +inline error_code SymbolRef::getName(StringRef &Result) const { + return OwningObject->getSymbolName(SymbolPimpl, Result); } -inline uint64_t SymbolRef::getAddress() const { - return OwningObject->getSymbolAddress(SymbolPimpl); +inline error_code SymbolRef::getAddress(uint64_t &Result) const { + return OwningObject->getSymbolAddress(SymbolPimpl, Result); } -inline uint64_t SymbolRef::getSize() const { - return OwningObject->getSymbolSize(SymbolPimpl); +inline error_code SymbolRef::getSize(uint64_t &Result) const { + return OwningObject->getSymbolSize(SymbolPimpl, Result); } -inline char SymbolRef::getNMTypeChar() const { - return OwningObject->getSymbolNMTypeChar(SymbolPimpl); +inline error_code SymbolRef::getNMTypeChar(char &Result) const { + return OwningObject->getSymbolNMTypeChar(SymbolPimpl, Result); } -inline bool SymbolRef::isInternal() const { - return OwningObject->isSymbolInternal(SymbolPimpl); +inline error_code SymbolRef::isInternal(bool &Result) const { + return OwningObject->isSymbolInternal(SymbolPimpl, Result); } @@ -232,28 +254,28 @@ inline bool SectionRef::operator==(const SectionRef &Other) const { return SectionPimpl == Other.SectionPimpl; } -inline SectionRef SectionRef::getNext() const { - return OwningObject->getSectionNext(SectionPimpl); +inline error_code SectionRef::getNext(SectionRef &Result) const { + return OwningObject->getSectionNext(SectionPimpl, Result); } -inline StringRef SectionRef::getName() const { - return OwningObject->getSectionName(SectionPimpl); +inline error_code SectionRef::getName(StringRef &Result) const { + return OwningObject->getSectionName(SectionPimpl, Result); } -inline uint64_t SectionRef::getAddress() const { - return OwningObject->getSectionAddress(SectionPimpl); +inline error_code SectionRef::getAddress(uint64_t &Result) const { + return OwningObject->getSectionAddress(SectionPimpl, Result); } -inline uint64_t SectionRef::getSize() const { - return OwningObject->getSectionSize(SectionPimpl); +inline error_code SectionRef::getSize(uint64_t &Result) const { + return OwningObject->getSectionSize(SectionPimpl, Result); } -inline StringRef SectionRef::getContents() const { - return OwningObject->getSectionContents(SectionPimpl); +inline error_code SectionRef::getContents(StringRef &Result) const { + return OwningObject->getSectionContents(SectionPimpl, Result); } -inline bool SectionRef::isText() const { - return OwningObject->isSectionText(SectionPimpl); +inline error_code SectionRef::isText(bool &Result) const { + return OwningObject->isSectionText(SectionPimpl, Result); } } // end namespace object diff --git a/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h index 7ba6491..c66d224 100644 --- a/include/llvm/Support/BranchProbability.h +++ b/include/llvm/Support/BranchProbability.h @@ -18,13 +18,17 @@ namespace llvm { -class raw_ostream; +template<class BlockT, class FunctionT, class BranchProbInfoT> +class BlockFrequencyImpl; class BranchProbabilityInfo; class MachineBranchProbabilityInfo; class MachineBasicBlock; +class raw_ostream; // This class represents Branch Probability as a non-negative fraction. class BranchProbability { + template<class BlockT, class FunctionT, class BranchProbInfoT> + friend class BlockFrequencyImpl; friend class BranchProbabilityInfo; friend class MachineBranchProbabilityInfo; friend class MachineBasicBlock; @@ -38,6 +42,10 @@ class BranchProbability { BranchProbability(uint32_t n, uint32_t d); public: + + uint32_t getNumerator() const { return N; } + uint32_t getDenominator() const { return D; } + raw_ostream &print(raw_ostream &OS) const; void dump() const; diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index 6a7c277..9459280 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -82,7 +82,7 @@ public: InsertPt = I; SetCurrentDebugLocation(I->getDebugLoc()); } - + /// SetInsertPoint - This specifies that created instructions should be /// inserted at the specified point. void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { @@ -90,6 +90,19 @@ public: InsertPt = IP; } + /// SetInsertPoint(Use) - Find the nearest point that dominates this use, and + /// specify that created instructions should be inserted at this point. + void SetInsertPoint(Use &U) { + Instruction *UseInst = cast<Instruction>(U.getUser()); + if (PHINode *Phi = dyn_cast<PHINode>(UseInst)) { + BasicBlock *PredBB = Phi->getIncomingBlock(U); + assert(U != PredBB->getTerminator() && "critical edge not split"); + SetInsertPoint(PredBB, PredBB->getTerminator()); + return; + } + SetInsertPoint(UseInst); + } + /// SetCurrentDebugLocation - Set location information used by debugging /// information. void SetCurrentDebugLocation(const DebugLoc &L) { @@ -110,7 +123,7 @@ public: /// getCurrentFunctionReturnType - Get the return type of the current function /// that we're emitting into. const Type *getCurrentFunctionReturnType() const; - + /// InsertPoint - A saved insertion point. class InsertPoint { BasicBlock *Block; @@ -198,7 +211,7 @@ public: ConstantInt *getInt64(uint64_t C) { return ConstantInt::get(getInt64Ty(), C); } - + /// getInt - Get a constant integer value. ConstantInt *getInt(const APInt &AI) { return ConstantInt::get(Context, AI); @@ -263,7 +276,7 @@ public: bool isVolatile = false, MDNode *TBAATag = 0) { return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); } - + CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = 0); @@ -274,7 +287,7 @@ public: bool isVolatile = false, MDNode *TBAATag = 0) { return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); } - + CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = 0); @@ -285,9 +298,9 @@ public: bool isVolatile = false, MDNode *TBAATag = 0) { return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); } - + CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0); + bool isVolatile = false, MDNode *TBAATag = 0); /// CreateLifetimeStart - Create a lifetime.start intrinsic. If the pointer /// isn't i8* it will be converted. @@ -341,7 +354,13 @@ public: SetInsertPoint(IP); SetCurrentDebugLocation(IP->getDebugLoc()); } - + + explicit IRBuilder(Use &U) + : IRBuilderBase(U->getContext()), Folder() { + SetInsertPoint(U); + SetCurrentDebugLocation(cast<Instruction>(U.getUser())->getDebugLoc()); + } + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F) : IRBuilderBase(TheBB->getContext()), Folder(F) { SetInsertPoint(TheBB, IP); diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index bc8be89..4d7116b 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -26,11 +26,19 @@ class SubRegIndex { string Namespace = ""; } +// RegAltNameIndex - The alternate name set to use for register operands of +// this register class when printing. +class RegAltNameIndex { + string Namespace = ""; +} +def NoRegAltName : RegAltNameIndex; + // Register - You should define one instance of this class for each register // in the target machine. String n will become the "name" of the register. -class Register<string n> { +class Register<string n, list<string> altNames = []> { string Namespace = ""; string AsmName = n; + list<string> AltNames = altNames; // Aliases - A list of registers that this register overlaps with. A read or // modification of this register can potentially read or modify the aliased @@ -48,6 +56,10 @@ class Register<string n> { // SubRegs. list<SubRegIndex> SubRegIndices = []; + // RegAltNameIndices - The alternate name indices which are valid for this + // register. + list<RegAltNameIndex> RegAltNameIndices = []; + // CompositeIndices - Specify subreg indices that don't correspond directly to // a register in SubRegs and are not inherited. The following formats are // supported: @@ -92,7 +104,7 @@ class RegisterWithSubRegs<string n, list<Register> subregs> : Register<n> { // registers by register allocators. // class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, - dag regList> { + dag regList, RegAltNameIndex idx = NoRegAltName> { string Namespace = namespace; // RegType - Specify the list ValueType of the registers in this register @@ -124,6 +136,11 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // dag MemberList = regList; + // AltNameIndex - The alternate register name to use when printing operands + // of this register class. Every register in the register class must have + // a valid alternate name for the given index. + RegAltNameIndex altNameIndex = idx; + // SubRegClasses - Specify the register class of subregisters as a list of // dags: (RegClass SubRegIndex, SubRegindex, ...) list<dag> SubRegClasses = []; @@ -466,6 +483,24 @@ class Operand<ValueType ty> { AsmOperandClass ParserMatchClass = ImmAsmOperand; } +class RegisterOperand<RegisterClass regclass, string pm = "printOperand"> { + // RegClass - The register class of the operand. + RegisterClass RegClass = regclass; + // PrintMethod - The target method to call to print register operands of + // this type. The method normally will just use an alt-name index to look + // up the name to print. Default to the generic printOperand(). + string PrintMethod = pm; + // ParserMatchClass - The "match class" that operands of this type fit + // in. Match classes are used to define the order in which instructions are + // match, to ensure that which instructions gets matched is deterministic. + // + // The target specific parser must be able to classify an parsed operand into + // a unique class, which does not partially overlap with any other classes. It + // can match a subset of some other class, in which case the AsmOperandClass + // should declare the other operand as one of its super classes. + AsmOperandClass ParserMatchClass; +} + def i1imm : Operand<i1>; def i8imm : Operand<i8>; def i16imm : Operand<i16>; diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h index abaed81..1a417a1 100644 --- a/include/llvm/Target/TargetAsmInfo.h +++ b/include/llvm/Target/TargetAsmInfo.h @@ -106,6 +106,10 @@ public: int getSEHRegNum(unsigned RegNum) const { return TRI->getSEHRegNum(RegNum); } + + int getCompactUnwindRegNum(unsigned RegNum) const { + return TRI->getCompactUnwindRegNum(RegNum); + } }; } diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 418f3fe..70969eb 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -14,7 +14,7 @@ #ifndef LLVM_TARGET_TARGETINSTRINFO_H #define LLVM_TARGET_TARGETINSTRINFO_H -#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/CodeGen/MachineFunction.h" namespace llvm { @@ -40,25 +40,20 @@ template<class T> class SmallVectorImpl; /// /// TargetInstrInfo - Interface to description of machine instruction set /// -class TargetInstrInfo { - const TargetInstrDesc *Descriptors; // Raw array to allow static init'n - unsigned NumOpcodes; // Number of entries in the desc array - +class TargetInstrInfo : public MCInstrInfo { TargetInstrInfo(const TargetInstrInfo &); // DO NOT IMPLEMENT void operator=(const TargetInstrInfo &); // DO NOT IMPLEMENT public: - TargetInstrInfo(const TargetInstrDesc *desc, unsigned NumOpcodes); + TargetInstrInfo(const MCInstrDesc *desc, unsigned NumOpcodes, + int CallFrameSetupOpcode = -1, + int CallFrameDestroyOpcode = -1); virtual ~TargetInstrInfo(); - unsigned getNumOpcodes() const { return NumOpcodes; } - - /// get - Return the machine instruction descriptor that corresponds to the - /// specified instruction opcode. - /// - const TargetInstrDesc &get(unsigned Opcode) const { - assert(Opcode < NumOpcodes && "Invalid opcode!"); - return Descriptors[Opcode]; - } + /// getRegClass - Givem a machine instruction descriptor, returns the register + /// class constraint for OpNum, or NULL. + const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, + unsigned OpNum, + const TargetRegisterInfo *TRI) const; /// isTriviallyReMaterializable - Return true if the instruction is trivially /// rematerializable, meaning it has no side effects and requires no operands @@ -93,6 +88,15 @@ private: AliasAnalysis *AA) const; public: + /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the + /// frame setup/destroy instructions if they exist (-1 otherwise). Some + /// targets use pseudo instructions in order to abstract away the difference + /// between operating with a frame pointer and operating without, through the + /// use of these two instructions. + /// + int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } + int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } + /// isCoalescableExtInstr - Return true if the instruction is a "coalescable" /// extension instruction. That is, it's like a copy where it's legal for the /// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns @@ -663,6 +667,9 @@ public: virtual bool hasLowDefLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx) const; + +private: + int CallFrameSetupOpcode, CallFrameDestroyOpcode; }; /// TargetInstrInfoImpl - This is the default implementation of @@ -671,8 +678,11 @@ public: /// libcodegen, not in libtarget. class TargetInstrInfoImpl : public TargetInstrInfo { protected: - TargetInstrInfoImpl(const TargetInstrDesc *desc, unsigned NumOpcodes) - : TargetInstrInfo(desc, NumOpcodes) {} + TargetInstrInfoImpl(const MCInstrDesc *desc, unsigned NumOpcodes, + int CallFrameSetupOpcode = -1, + int CallFrameDestroyOpcode = -1) + : TargetInstrInfo(desc, NumOpcodes, + CallFrameSetupOpcode, CallFrameDestroyOpcode) {} public: virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst, MachineBasicBlock *NewDest) const; diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index c3f5f2b..f684163 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -1421,13 +1421,6 @@ public: /// is for this target. virtual ConstraintType getConstraintType(const std::string &Constraint) const; - /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), - /// return a list of registers that can be used to satisfy the constraint. - /// This should only be used for C_RegisterClass constraints. - virtual std::vector<unsigned> - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; - /// getRegForInlineAsmConstraint - Given a physical register constraint (e.g. /// {edx}), return the register number and the register class for the /// register. diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 78f770c..6544ce2 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -14,29 +14,29 @@ #ifndef LLVM_TARGET_TARGETMACHINE_H #define LLVM_TARGET_TARGETMACHINE_H -#include "llvm/Target/TargetInstrItineraries.h" #include <cassert> #include <string> namespace llvm { -class Target; +class InstrItineraryData; +class JITCodeEmitter; class MCAsmInfo; +class MCContext; +class Pass; +class PassManager; +class PassManagerBase; +class Target; class TargetData; -class TargetSubtarget; +class TargetELFWriterInfo; +class TargetFrameLowering; class TargetInstrInfo; class TargetIntrinsicInfo; class TargetJITInfo; class TargetLowering; -class TargetSelectionDAGInfo; -class TargetFrameLowering; -class JITCodeEmitter; -class MCContext; class TargetRegisterInfo; -class PassManagerBase; -class PassManager; -class Pass; -class TargetELFWriterInfo; +class TargetSelectionDAGInfo; +class TargetSubtarget; class formatted_raw_ostream; class raw_ostream; diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index beed039..55d50d9 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -133,8 +133,8 @@ namespace llvm { /// as their parent function, etc.), using an alternate ABI if necessary. extern bool GuaranteedTailCallOpt; - /// StackAlignment - Override default stack alignment for target. - extern unsigned StackAlignment; + /// StackAlignmentOverride - Override default stack alignment for target. + extern unsigned StackAlignmentOverride; /// RealignStack - This flag indicates whether the stack should be /// automatically realigned, if needed. diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 840b048..3f28f6c 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -16,6 +16,7 @@ #ifndef LLVM_TARGET_TARGETREGISTERINFO_H #define LLVM_TARGET_TARGETREGISTERINFO_H +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/ADT/ArrayRef.h" @@ -27,30 +28,10 @@ namespace llvm { class BitVector; class MachineFunction; -class MachineMove; class RegScavenger; template<class T> class SmallVectorImpl; class raw_ostream; -/// TargetRegisterDesc - This record contains all of the information known about -/// a particular register. The Overlaps field contains a pointer to a zero -/// terminated array of registers that this register aliases, starting with -/// itself. This is needed for architectures like X86 which have AL alias AX -/// alias EAX. The SubRegs field is a zero terminated array of registers that -/// are sub-registers of the specific register, e.g. AL, AH are sub-registers of -/// AX. The SuperRegs field is a zero terminated array of registers that are -/// super-registers of the specific register, e.g. RAX, EAX, are super-registers -/// of AX. -/// -struct TargetRegisterDesc { - const char *Name; // Printable name for the reg (for debugging) - const unsigned *Overlaps; // Overlapping registers, described above - const unsigned *SubRegs; // Sub-register set, described above - const unsigned *SuperRegs; // Super-register set, described above - unsigned CostPerUse; // Extra cost of instructions using register. - bool inAllocatableClass; // Register belongs to an allocatable regclass. -}; - class TargetRegisterClass { public: typedef const unsigned* iterator; @@ -274,6 +255,12 @@ public: bool isAllocatable() const { return Allocatable; } }; +/// TargetRegisterInfoDesc - Extra information, not in MCRegisterDesc, about +/// registers. These are used by codegen, not by MC. +struct TargetRegisterInfoDesc { + unsigned CostPerUse; // Extra cost of instructions using register. + bool inAllocatableClass; // Register belongs to an allocatable regclass. +}; /// TargetRegisterInfo base class - We assume that the target defines a static /// array of TargetRegisterDesc objects that represent all of the machine @@ -281,25 +268,19 @@ public: /// to this array so that we can turn register number into a register /// descriptor. /// -class TargetRegisterInfo { +class TargetRegisterInfo : public MCRegisterInfo { public: typedef const TargetRegisterClass * const * regclass_iterator; private: - const TargetRegisterDesc *Desc; // Pointer to the descriptor array + const TargetRegisterInfoDesc *InfoDesc; // Extra desc array for codegen const char *const *SubRegIndexNames; // Names of subreg indexes. - unsigned NumRegs; // Number of entries in the array - regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses - int CallFrameSetupOpcode, CallFrameDestroyOpcode; - protected: - TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR, + TargetRegisterInfo(const TargetRegisterInfoDesc *ID, regclass_iterator RegClassBegin, regclass_iterator RegClassEnd, - const char *const *subregindexnames, - int CallFrameSetupOpcode = -1, - int CallFrameDestroyOpcode = -1); + const char *const *subregindexnames); virtual ~TargetRegisterInfo(); public: @@ -379,71 +360,16 @@ public: BitVector getAllocatableSet(const MachineFunction &MF, const TargetRegisterClass *RC = NULL) const; - const TargetRegisterDesc &operator[](unsigned RegNo) const { - assert(RegNo < NumRegs && - "Attempting to access record for invalid register number!"); - return Desc[RegNo]; - } - - /// Provide a get method, equivalent to [], but more useful if we have a - /// pointer to this object. - /// - const TargetRegisterDesc &get(unsigned RegNo) const { - return operator[](RegNo); - } - - /// getAliasSet - Return the set of registers aliased by the specified - /// register, or a null list of there are none. The list returned is zero - /// terminated. - /// - const unsigned *getAliasSet(unsigned RegNo) const { - // The Overlaps set always begins with Reg itself. - return get(RegNo).Overlaps + 1; - } - - /// getOverlaps - Return a list of registers that overlap Reg, including - /// itself. This is the same as the alias set except Reg is included in the - /// list. - /// These are exactly the registers in { x | regsOverlap(x, Reg) }. - /// - const unsigned *getOverlaps(unsigned RegNo) const { - return get(RegNo).Overlaps; - } - - /// getSubRegisters - Return the list of registers that are sub-registers of - /// the specified register, or a null list of there are none. The list - /// returned is zero terminated and sorted according to super-sub register - /// relations. e.g. X86::RAX's sub-register list is EAX, AX, AL, AH. - /// - const unsigned *getSubRegisters(unsigned RegNo) const { - return get(RegNo).SubRegs; - } - - /// getSuperRegisters - Return the list of registers that are super-registers - /// of the specified register, or a null list of there are none. The list - /// returned is zero terminated and sorted according to super-sub register - /// relations. e.g. X86::AL's super-register list is AX, EAX, RAX. - /// - const unsigned *getSuperRegisters(unsigned RegNo) const { - return get(RegNo).SuperRegs; - } - - /// getName - Return the human-readable symbolic target-specific name for the - /// specified physical register. - const char *getName(unsigned RegNo) const { - return get(RegNo).Name; - } - /// getCostPerUse - Return the additional cost of using this register instead /// of other registers in its class. unsigned getCostPerUse(unsigned RegNo) const { - return get(RegNo).CostPerUse; + return InfoDesc[RegNo].CostPerUse; } - /// getNumRegs - Return the number of registers this target has (useful for - /// sizing arrays holding per register information) - unsigned getNumRegs() const { - return NumRegs; + /// isInAllocatableClass - Return true if the register is in the allocation + /// of any register class. + bool isInAllocatableClass(unsigned RegNo) const { + return InfoDesc[RegNo].inAllocatableClass; } /// getSubRegIndexName - Return the human-readable symbolic target-specific @@ -566,7 +492,7 @@ public: } /// getRegClass - Returns the register class associated with the enumeration - /// value. See class TargetOperandInfo. + /// value. See class MCOperandInfo. const TargetRegisterClass *getRegClass(unsigned i) const { assert(i < getNumRegClasses() && "Register Class ID out of range"); return RegClassBegin[i]; @@ -732,15 +658,6 @@ public: return false; // Must return a value in order to compile with VS 2005 } - /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the - /// frame setup/destroy instructions if they exist (-1 otherwise). Some - /// targets use pseudo instructions in order to abstract away the difference - /// between operating with a frame pointer and operating without, through the - /// use of these two instructions. - /// - int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } - int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } - /// eliminateCallFramePseudoInstr - This method is called during prolog/epilog /// code insertion to eliminate call frame setup and destroy pseudo /// instructions (but only if the Target is using them). It is responsible @@ -752,9 +669,6 @@ public: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { - assert(getCallFrameSetupOpcode()== -1 && getCallFrameDestroyOpcode()== -1 && - "eliminateCallFramePseudoInstr must be implemented if using" - " call frame setup/destroy pseudo instructions!"); assert(0 && "Call Frame Pseudo Instructions do not exist on this target!"); } @@ -806,6 +720,12 @@ public: virtual int getSEHRegNum(unsigned i) const { return i; } + + /// getCompactUnwindRegNum - This function maps the register to the number for + /// compact unwind encoding. Return -1 if the register isn't valid. + virtual int getCompactUnwindRegNum(unsigned) const { + return -1; + } }; diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index a464822..8d44f66 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -33,6 +33,8 @@ namespace llvm { class MCContext; class MCDisassembler; class MCInstPrinter; + class MCInstrInfo; + class MCRegisterInfo; class MCStreamer; class TargetAsmBackend; class TargetAsmLexer; @@ -64,9 +66,12 @@ namespace llvm { typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT); typedef MCAsmInfo *(*AsmInfoCtorFnTy)(const Target &T, - StringRef TT); + StringRef TT); + typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); + typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(void); typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &Features); typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM, MCStreamer &Streamer); @@ -120,8 +125,18 @@ namespace llvm { /// HasJIT - Whether this target supports the JIT. bool HasJIT; + /// AsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if + /// registered. AsmInfoCtorFnTy AsmInfoCtorFn; + /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo, + /// if registered. + MCInstrInfoCtorFnTy MCInstrInfoCtorFn; + + /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo, + /// if registered. + MCRegInfoCtorFnTy MCRegInfoCtorFn; + /// TargetMachineCtorFn - Construction function for this target's /// TargetMachine, if registered. TargetMachineCtorTy TargetMachineCtorFn; @@ -231,6 +246,22 @@ namespace llvm { return AsmInfoCtorFn(*this, Triple); } + /// createMCInstrInfo - Create a MCInstrInfo implementation. + /// + MCInstrInfo *createMCInstrInfo() const { + if (!MCInstrInfoCtorFn) + return 0; + return MCInstrInfoCtorFn(); + } + + /// createMCRegInfo - Create a MCRegisterInfo implementation. + /// + MCRegisterInfo *createMCRegInfo() const { + if (!MCRegInfoCtorFn) + return 0; + return MCRegInfoCtorFn(); + } + /// createTargetMachine - Create a target specific machine implementation /// for the specified \arg Triple. /// @@ -239,10 +270,11 @@ namespace llvm { /// either the target triple from the module, or the target triple of the /// host if that does not exist. TargetMachine *createTargetMachine(const std::string &Triple, + const std::string &CPU, const std::string &Features) const { if (!TargetMachineCtorFn) return 0; - return TargetMachineCtorFn(*this, Triple, Features); + return TargetMachineCtorFn(*this, Triple, CPU, Features); } /// createAsmBackend - Create a target specific assembly parser. @@ -444,6 +476,36 @@ namespace llvm { T.AsmInfoCtorFn = Fn; } + /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCInstrInfo for the target. + static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) { + // Ignore duplicate registration. + if (!T.MCInstrInfoCtorFn) + T.MCInstrInfoCtorFn = Fn; + } + + /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCRegisterInfo for the target. + static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) { + // Ignore duplicate registration. + if (!T.MCRegInfoCtorFn) + T.MCRegInfoCtorFn = Fn; + } + /// RegisterTargetMachine - Register a TargetMachine implementation for the /// given target. /// @@ -654,6 +716,71 @@ namespace llvm { } }; + /// RegisterMCInstrInfo - Helper template for registering a target instruction + /// info implementation. This invokes the static "Create" method on the class + /// to actually do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCInstrInfo<FooMCInstrInfo> X(TheFooTarget); + /// } + template<class MCInstrInfoImpl> + struct RegisterMCInstrInfo { + RegisterMCInstrInfo(Target &T) { + TargetRegistry::RegisterMCInstrInfo(T, &Allocator); + } + private: + static MCInstrInfo *Allocator() { + return new MCInstrInfoImpl(); + } + }; + + /// RegisterMCInstrInfoFn - Helper template for registering a target + /// instruction info implementation. This invokes the specified function to + /// do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction); + /// } + struct RegisterMCInstrInfoFn { + RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCInstrInfo(T, Fn); + } + }; + + /// RegisterMCRegInfo - Helper template for registering a target register info + /// implementation. This invokes the static "Create" method on the class to + /// actually do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCRegInfo<FooMCRegInfo> X(TheFooTarget); + /// } + template<class MCRegisterInfoImpl> + struct RegisterMCRegInfo { + RegisterMCRegInfo(Target &T) { + TargetRegistry::RegisterMCRegInfo(T, &Allocator); + } + private: + static MCRegisterInfo *Allocator() { + return new MCRegisterInfoImpl(); + } + }; + + /// RegisterMCRegInfoFn - Helper template for registering a target register + /// info implementation. This invokes the specified function to do the + /// construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCRegInfoFn X(TheFooTarget, TheFunction); + /// } + struct RegisterMCRegInfoFn { + RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCRegInfo(T, Fn); + } + }; /// RegisterTargetMachine - Helper template for registering a target machine /// implementation, for use in the target machine initialization @@ -671,8 +798,9 @@ namespace llvm { private: static TargetMachine *Allocator(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) { - return new TargetMachineImpl(T, TT, FS); + return new TargetMachineImpl(T, TT, CPU, FS); } }; |
