Update Makefiles and other build glue for llvm/clang 3.7.0, as of trunk

r239412.
This commit is contained in:
Dimitry Andric 2015-06-10 19:12:52 +00:00
commit 97bc6c731e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang-trunk/; revision=284236
710 changed files with 28231 additions and 18945 deletions

View File

@ -997,6 +997,13 @@ unsigned LLVMCountStructElementTypes(LLVMTypeRef StructTy);
*/ */
void LLVMGetStructElementTypes(LLVMTypeRef StructTy, LLVMTypeRef *Dest); void LLVMGetStructElementTypes(LLVMTypeRef StructTy, LLVMTypeRef *Dest);
/**
* Get the type of the element at a given index in the structure.
*
* @see llvm::StructType::getTypeAtIndex()
*/
LLVMTypeRef LLVMStructGetTypeAtIndex(LLVMTypeRef StructTy, unsigned i);
/** /**
* Determine whether a structure is packed. * Determine whether a structure is packed.
* *

View File

@ -58,6 +58,24 @@ LLVMBool LLVMLoadLibraryPermanently(const char* Filename);
void LLVMParseCommandLineOptions(int argc, const char *const *argv, void LLVMParseCommandLineOptions(int argc, const char *const *argv,
const char *Overview); const char *Overview);
/**
* This function will search through all previously loaded dynamic
* libraries for the symbol \p symbolName. If it is found, the address of
* that symbol is returned. If not, null is returned.
*
* @see sys::DynamicLibrary::SearchForAddressOfSymbol()
*/
void *LLVMSearchForAddressOfSymbol(const char *symbolName);
/**
* This functions permanently adds the symbol \p symbolName with the
* value \p symbolValue. These symbols are searched before any
* libraries.
*
* @see sys::DynamicLibrary::AddSymbol()
*/
void LLVMAddSymbol(const char *symbolName, void *symbolValue);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -351,8 +351,7 @@ class APInt {
/// This checks to see if the value of this APInt is the maximum signed /// This checks to see if the value of this APInt is the maximum signed
/// value for the APInt's bit width. /// value for the APInt's bit width.
bool isMaxSignedValue() const { bool isMaxSignedValue() const {
return BitWidth == 1 ? VAL == 0 return !isNegative() && countPopulation() == BitWidth - 1;
: !isNegative() && countPopulation() == BitWidth - 1;
} }
/// \brief Determine if this is the smallest unsigned value. /// \brief Determine if this is the smallest unsigned value.
@ -366,7 +365,7 @@ class APInt {
/// This checks to see if the value of this APInt is the minimum signed /// This checks to see if the value of this APInt is the minimum signed
/// value for the APInt's bit width. /// value for the APInt's bit width.
bool isMinSignedValue() const { bool isMinSignedValue() const {
return BitWidth == 1 ? VAL == 1 : isNegative() && isPowerOf2(); return isNegative() && isPowerOf2();
} }
/// \brief Check if this APInt has an N-bits unsigned integer value. /// \brief Check if this APInt has an N-bits unsigned integer value.

View File

@ -50,7 +50,8 @@ class Triple {
armeb, // ARM (big endian): armeb armeb, // ARM (big endian): armeb
aarch64, // AArch64 (little endian): aarch64 aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be aarch64_be, // AArch64 (big endian): aarch64_be
bpf, // eBPF or extended BPF or 64-bit BPF (little endian) bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
hexagon, // Hexagon: hexagon hexagon, // Hexagon: hexagon
mips, // MIPS: mips, mipsallegrex mips, // MIPS: mips, mipsallegrex
mipsel, // MIPSEL: mipsel, mipsallegrexel mipsel, // MIPSEL: mipsel, mipsallegrexel
@ -255,6 +256,15 @@ class Triple {
/// getEnvironment - Get the parsed environment type of this triple. /// getEnvironment - Get the parsed environment type of this triple.
EnvironmentType getEnvironment() const { return Environment; } EnvironmentType getEnvironment() const { return Environment; }
/// \brief Parse the version number from the OS name component of the
/// triple, if present.
///
/// For example, "fooos1.2.3" would return (1, 2, 3).
///
/// If an entry is not defined, it will be returned as 0.
void getEnvironmentVersion(unsigned &Major, unsigned &Minor,
unsigned &Micro) const;
/// getFormat - Get the object format for this triple. /// getFormat - Get the object format for this triple.
ObjectFormatType getObjectFormat() const { return ObjectFormat; } ObjectFormatType getObjectFormat() const { return ObjectFormat; }

View File

@ -40,6 +40,7 @@
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/IR/CallSite.h" #include "llvm/IR/CallSite.h"
#include "llvm/IR/Metadata.h" #include "llvm/IR/Metadata.h"
#include "llvm/Analysis/MemoryLocation.h"
namespace llvm { namespace llvm {
@ -82,7 +83,7 @@ class AliasAnalysis {
/// UnknownSize - This is a special value which can be used with the /// UnknownSize - This is a special value which can be used with the
/// size arguments in alias queries to indicate that the caller does not /// size arguments in alias queries to indicate that the caller does not
/// know the sizes of the potential memory references. /// know the sizes of the potential memory references.
static uint64_t const UnknownSize = ~UINT64_C(0); static uint64_t const UnknownSize = MemoryLocation::UnknownSize;
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo /// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
/// object, or null if no TargetLibraryInfo object is available. /// object, or null if no TargetLibraryInfo object is available.
@ -98,70 +99,9 @@ class AliasAnalysis {
/// Alias Queries... /// Alias Queries...
/// ///
/// Location - A description of a memory location. /// Legacy typedef for the AA location object. New code should use \c
struct Location { /// MemoryLocation directly.
/// Ptr - The address of the start of the location. typedef MemoryLocation Location;
const Value *Ptr;
/// Size - The maximum size of the location, in address-units, or
/// UnknownSize if the size is not known. Note that an unknown size does
/// not mean the pointer aliases the entire virtual address space, because
/// there are restrictions on stepping out of one object and into another.
/// See http://llvm.org/docs/LangRef.html#pointeraliasing
uint64_t Size;
/// AATags - The metadata nodes which describes the aliasing of the
/// location (each member is null if that kind of information is
/// unavailable)..
AAMDNodes AATags;
explicit Location(const Value *P = nullptr, uint64_t S = UnknownSize,
const AAMDNodes &N = AAMDNodes())
: Ptr(P), Size(S), AATags(N) {}
Location getWithNewPtr(const Value *NewPtr) const {
Location Copy(*this);
Copy.Ptr = NewPtr;
return Copy;
}
Location getWithNewSize(uint64_t NewSize) const {
Location Copy(*this);
Copy.Size = NewSize;
return Copy;
}
Location getWithoutAATags() const {
Location Copy(*this);
Copy.AATags = AAMDNodes();
return Copy;
}
bool operator==(const AliasAnalysis::Location &Other) const {
return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags;
}
};
/// getLocation - Fill in Loc with information about the memory reference by
/// the given instruction.
Location getLocation(const LoadInst *LI);
Location getLocation(const StoreInst *SI);
Location getLocation(const VAArgInst *VI);
Location getLocation(const AtomicCmpXchgInst *CXI);
Location getLocation(const AtomicRMWInst *RMWI);
static Location getLocationForSource(const MemTransferInst *MTI);
static Location getLocationForDest(const MemIntrinsic *MI);
Location getLocation(const Instruction *Inst) {
if (auto *I = dyn_cast<LoadInst>(Inst))
return getLocation(I);
else if (auto *I = dyn_cast<StoreInst>(Inst))
return getLocation(I);
else if (auto *I = dyn_cast<VAArgInst>(Inst))
return getLocation(I);
else if (auto *I = dyn_cast<AtomicCmpXchgInst>(Inst))
return getLocation(I);
else if (auto *I = dyn_cast<AtomicRMWInst>(Inst))
return getLocation(I);
llvm_unreachable("unsupported memory instruction");
}
/// Alias analysis result - Either we know for sure that it does not alias, we /// Alias analysis result - Either we know for sure that it does not alias, we
/// know for sure it must alias, or we don't know anything: The two pointers /// know for sure it must alias, or we don't know anything: The two pointers
@ -601,28 +541,6 @@ class AliasAnalysis {
} }
}; };
// Specialize DenseMapInfo for Location.
template<>
struct DenseMapInfo<AliasAnalysis::Location> {
static inline AliasAnalysis::Location getEmptyKey() {
return AliasAnalysis::Location(DenseMapInfo<const Value *>::getEmptyKey(),
0);
}
static inline AliasAnalysis::Location getTombstoneKey() {
return AliasAnalysis::Location(
DenseMapInfo<const Value *>::getTombstoneKey(), 0);
}
static unsigned getHashValue(const AliasAnalysis::Location &Val) {
return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^
DenseMapInfo<uint64_t>::getHashValue(Val.Size) ^
DenseMapInfo<AAMDNodes>::getHashValue(Val.AATags);
}
static bool isEqual(const AliasAnalysis::Location &LHS,
const AliasAnalysis::Location &RHS) {
return LHS == RHS;
}
};
/// isNoAliasCall - Return true if this pointer is returned by a noalias /// isNoAliasCall - Return true if this pointer is returned by a noalias
/// function. /// function.
bool isNoAliasCall(const Value *V); bool isNoAliasCall(const Value *V);

View File

@ -191,8 +191,8 @@ class BlockFrequencyInfoImplBase {
/// \brief Data about a loop. /// \brief Data about a loop.
/// ///
/// Contains the data necessary to represent represent a loop as a /// Contains the data necessary to represent a loop as a pseudo-node once it's
/// pseudo-node once it's packaged. /// packaged.
struct LoopData { struct LoopData {
typedef SmallVector<std::pair<BlockNode, BlockMass>, 4> ExitMap; typedef SmallVector<std::pair<BlockNode, BlockMass>, 4> ExitMap;
typedef SmallVector<BlockNode, 4> NodeList; typedef SmallVector<BlockNode, 4> NodeList;
@ -930,7 +930,7 @@ void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F,
initializeRPOT(); initializeRPOT();
initializeLoops(); initializeLoops();
// Visit loops in post-order to find thelocal mass distribution, and then do // Visit loops in post-order to find the local mass distribution, and then do
// the full function. // the full function.
computeMassInLoops(); computeMassInLoops();
computeMassInFunction(); computeMassInFunction();

View File

@ -47,6 +47,9 @@ class BranchProbabilityInfo : public FunctionPass {
void getAnalysisUsage(AnalysisUsage &AU) const override; void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override; bool runOnFunction(Function &F) override;
void releaseMemory() override;
void print(raw_ostream &OS, const Module *M = nullptr) const override; void print(raw_ostream &OS, const Module *M = nullptr) const override;
/// \brief Get an edge's probability, relative to other out-edges of the Src. /// \brief Get an edge's probability, relative to other out-edges of the Src.

View File

@ -230,7 +230,7 @@ class CallGraphNode {
void addCalledFunction(CallSite CS, CallGraphNode *M) { void addCalledFunction(CallSite CS, CallGraphNode *M) {
assert(!CS.getInstruction() || !CS.getCalledFunction() || assert(!CS.getInstruction() || !CS.getCalledFunction() ||
!CS.getCalledFunction()->isIntrinsic()); !CS.getCalledFunction()->isIntrinsic());
CalledFunctions.push_back(std::make_pair(CS.getInstruction(), M)); CalledFunctions.emplace_back(CS.getInstruction(), M);
M->AddRef(); M->AddRef();
} }

View File

@ -41,6 +41,7 @@
#define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H #define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H
#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
@ -520,11 +521,11 @@ namespace llvm {
/// in LoopNest. /// in LoopNest.
bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const; bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const;
/// Makes sure both subscripts (i.e. Pair->Src and Pair->Dst) share the same /// Makes sure all subscript pairs share the same integer type by
/// integer type by sign-extending one of them when necessary. /// sign-extending as necessary.
/// Sign-extending a subscript is safe because getelementptr assumes the /// Sign-extending a subscript is safe because getelementptr assumes the
/// array subscripts are signed. /// array subscripts are signed.
void unifySubscriptType(Subscript *Pair); void unifySubscriptType(ArrayRef<Subscript *> Pairs);
/// removeMatchingExtensions - Examines a subscript pair. /// removeMatchingExtensions - Examines a subscript pair.
/// If the source and destination are identically sign (or zero) /// If the source and destination are identically sign (or zero)

View File

@ -345,6 +345,10 @@ class LoopAccessInfo {
/// to needsChecking. /// to needsChecking.
bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const; bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Returns the number of run-time checks required according to
/// needsChecking.
unsigned getNumberOfChecks(const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Print the list run-time memory checks necessary. /// \brief Print the list run-time memory checks necessary.
/// ///
/// If \p PtrPartition is set, it contains the partition number for /// If \p PtrPartition is set, it contains the partition number for
@ -385,7 +389,10 @@ class LoopAccessInfo {
/// \brief Number of memchecks required to prove independence of otherwise /// \brief Number of memchecks required to prove independence of otherwise
/// may-alias pointers. /// may-alias pointers.
unsigned getNumRuntimePointerChecks() const { return NumComparisons; } unsigned getNumRuntimePointerChecks(
const SmallVectorImpl<int> *PtrPartition = nullptr) const {
return PtrRtCheck.getNumberOfChecks(PtrPartition);
}
/// Return true if the block BB needs to be predicated in order for the loop /// Return true if the block BB needs to be predicated in order for the loop
/// to be vectorized. /// to be vectorized.
@ -460,10 +467,6 @@ class LoopAccessInfo {
/// loop-independent and loop-carried dependences between memory accesses. /// loop-independent and loop-carried dependences between memory accesses.
MemoryDepChecker DepChecker; MemoryDepChecker DepChecker;
/// \brief Number of memchecks required to prove independence of otherwise
/// may-alias pointers
unsigned NumComparisons;
Loop *TheLoop; Loop *TheLoop;
ScalarEvolution *SE; ScalarEvolution *SE;
const DataLayout &DL; const DataLayout &DL;
@ -501,6 +504,11 @@ const SCEV *replaceSymbolicStrideSCEV(ScalarEvolution *SE,
const ValueToValueMap &PtrToStride, const ValueToValueMap &PtrToStride,
Value *Ptr, Value *OrigPtr = nullptr); Value *Ptr, Value *OrigPtr = nullptr);
/// \brief Check the stride of the pointer and ensure that it does not wrap in
/// the address space.
int isStridedPtr(ScalarEvolution *SE, Value *Ptr, const Loop *Lp,
const ValueToValueMap &StridesMap);
/// \brief This analysis provides dependence information for the memory accesses /// \brief This analysis provides dependence information for the memory accesses
/// of a loop. /// of a loop.
/// ///

View File

@ -47,13 +47,6 @@ namespace llvm {
template <typename IRUnitT> class AnalysisManager; template <typename IRUnitT> class AnalysisManager;
class PreservedAnalyses; class PreservedAnalyses;
template<typename T>
inline void RemoveFromVector(std::vector<T*> &V, T *N) {
typename std::vector<T*>::iterator I = std::find(V.begin(), V.end(), N);
assert(I != V.end() && "N is not in this list!");
V.erase(I);
}
class DominatorTree; class DominatorTree;
class LoopInfo; class LoopInfo;
class Loop; class Loop;
@ -324,7 +317,10 @@ class LoopBase {
/// current loop, updating the Blocks as appropriate. This does not update /// current loop, updating the Blocks as appropriate. This does not update
/// the mapping in the LoopInfo class. /// the mapping in the LoopInfo class.
void removeBlockFromLoop(BlockT *BB) { void removeBlockFromLoop(BlockT *BB) {
RemoveFromVector(Blocks, BB); auto I = std::find(Blocks.begin(), Blocks.end(), BB);
assert(I != Blocks.end() && "N is not in this list!");
Blocks.erase(I);
DenseBlockSet.erase(BB); DenseBlockSet.erase(BB);
} }
@ -493,7 +489,7 @@ class Loop : public LoopBase<BasicBlock, Loop> {
template<class BlockT, class LoopT> template<class BlockT, class LoopT>
class LoopInfoBase { class LoopInfoBase {
// BBMap - Mapping of basic blocks to the inner most loop they occur in // BBMap - Mapping of basic blocks to the inner most loop they occur in
DenseMap<BlockT *, LoopT *> BBMap; DenseMap<const BlockT *, LoopT *> BBMap;
std::vector<LoopT *> TopLevelLoops; std::vector<LoopT *> TopLevelLoops;
friend class LoopBase<BlockT, LoopT>; friend class LoopBase<BlockT, LoopT>;
friend class LoopInfo; friend class LoopInfo;
@ -543,9 +539,7 @@ class LoopInfoBase {
/// getLoopFor - Return the inner most loop that BB lives in. If a basic /// getLoopFor - Return the inner most loop that BB lives in. If a basic
/// block is in no loop (for example the entry node), null is returned. /// block is in no loop (for example the entry node), null is returned.
/// ///
LoopT *getLoopFor(const BlockT *BB) const { LoopT *getLoopFor(const BlockT *BB) const { return BBMap.lookup(BB); }
return BBMap.lookup(const_cast<BlockT*>(BB));
}
/// operator[] - same as getLoopFor... /// operator[] - same as getLoopFor...
/// ///
@ -562,7 +556,7 @@ class LoopInfoBase {
} }
// isLoopHeader - True if the block is a loop header node // isLoopHeader - True if the block is a loop header node
bool isLoopHeader(BlockT *BB) const { bool isLoopHeader(const BlockT *BB) const {
const LoopT *L = getLoopFor(BB); const LoopT *L = getLoopFor(BB);
return L && L->getHeader() == BB; return L && L->getHeader() == BB;
} }
@ -729,12 +723,6 @@ class LoopAnalysis {
/// \brief Provide a name for the analysis for debugging and logging. /// \brief Provide a name for the analysis for debugging and logging.
static StringRef name() { return "LoopAnalysis"; } static StringRef name() { return "LoopAnalysis"; }
LoopAnalysis() {}
LoopAnalysis(const LoopAnalysis &Arg) {}
LoopAnalysis(LoopAnalysis &&Arg) {}
LoopAnalysis &operator=(const LoopAnalysis &RHS) { return *this; }
LoopAnalysis &operator=(LoopAnalysis &&RHS) { return *this; }
LoopInfo run(Function &F, AnalysisManager<Function> *AM); LoopInfo run(Function &F, AnalysisManager<Function> *AM);
}; };

View File

@ -527,7 +527,7 @@ void LoopInfoBase<BlockT, LoopT>::verify() const {
// Verify that blocks are mapped to valid loops. // Verify that blocks are mapped to valid loops.
#ifndef NDEBUG #ifndef NDEBUG
for (auto &Entry : BBMap) { for (auto &Entry : BBMap) {
BlockT *BB = Entry.first; const BlockT *BB = Entry.first;
LoopT *L = Entry.second; LoopT *L = Entry.second;
assert(Loops.count(L) && "orphaned loop"); assert(Loops.count(L) && "orphaned loop");
assert(L->contains(BB) && "orphaned block"); assert(L->contains(BB) && "orphaned block");

View File

@ -0,0 +1,137 @@
//===- MemoryLocation.h - Memory location descriptions ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This file provides utility analysis objects describing memory locations.
/// These are used both by the Alias Analysis infrastructure and more
/// specialized memory analysis layers.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_MEMORYLOCATION_H
#define LLVM_ANALYSIS_MEMORYLOCATION_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Metadata.h"
namespace llvm {
class LoadInst;
class StoreInst;
class MemTransferInst;
class MemIntrinsic;
/// Representation for a specific memory location.
///
/// This abstraction can be used to represent a specific location in memory.
/// The goal of the location is to represent enough information to describe
/// abstract aliasing, modification, and reference behaviors of whatever
/// value(s) are stored in memory at the particular location.
///
/// The primary user of this interface is LLVM's Alias Analysis, but other
/// memory analyses such as MemoryDependence can use it as well.
class MemoryLocation {
public:
/// UnknownSize - This is a special value which can be used with the
/// size arguments in alias queries to indicate that the caller does not
/// know the sizes of the potential memory references.
enum : uint64_t { UnknownSize = ~UINT64_C(0) };
/// The address of the start of the location.
const Value *Ptr;
/// The maximum size of the location, in address-units, or
/// UnknownSize if the size is not known.
///
/// Note that an unknown size does not mean the pointer aliases the entire
/// virtual address space, because there are restrictions on stepping out of
/// one object and into another. See
/// http://llvm.org/docs/LangRef.html#pointeraliasing
uint64_t Size;
/// The metadata nodes which describes the aliasing of the location (each
/// member is null if that kind of information is unavailable).
AAMDNodes AATags;
/// Return a location with information about the memory reference by the given
/// instruction.
static MemoryLocation get(const LoadInst *LI);
static MemoryLocation get(const StoreInst *SI);
static MemoryLocation get(const VAArgInst *VI);
static MemoryLocation get(const AtomicCmpXchgInst *CXI);
static MemoryLocation get(const AtomicRMWInst *RMWI);
static MemoryLocation get(const Instruction *Inst) {
if (auto *I = dyn_cast<LoadInst>(Inst))
return get(I);
else if (auto *I = dyn_cast<StoreInst>(Inst))
return get(I);
else if (auto *I = dyn_cast<VAArgInst>(Inst))
return get(I);
else if (auto *I = dyn_cast<AtomicCmpXchgInst>(Inst))
return get(I);
else if (auto *I = dyn_cast<AtomicRMWInst>(Inst))
return get(I);
llvm_unreachable("unsupported memory instruction");
}
/// Return a location representing the source of a memory transfer.
static MemoryLocation getForSource(const MemTransferInst *MTI);
/// Return a location representing the destination of a memory set or
/// transfer.
static MemoryLocation getForDest(const MemIntrinsic *MI);
explicit MemoryLocation(const Value *Ptr = nullptr,
uint64_t Size = UnknownSize,
const AAMDNodes &AATags = AAMDNodes())
: Ptr(Ptr), Size(Size), AATags(AATags) {}
MemoryLocation getWithNewPtr(const Value *NewPtr) const {
MemoryLocation Copy(*this);
Copy.Ptr = NewPtr;
return Copy;
}
MemoryLocation getWithNewSize(uint64_t NewSize) const {
MemoryLocation Copy(*this);
Copy.Size = NewSize;
return Copy;
}
MemoryLocation getWithoutAATags() const {
MemoryLocation Copy(*this);
Copy.AATags = AAMDNodes();
return Copy;
}
bool operator==(const MemoryLocation &Other) const {
return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags;
}
};
// Specialize DenseMapInfo for MemoryLocation.
template <> struct DenseMapInfo<MemoryLocation> {
static inline MemoryLocation getEmptyKey() {
return MemoryLocation(DenseMapInfo<const Value *>::getEmptyKey(), 0);
}
static inline MemoryLocation getTombstoneKey() {
return MemoryLocation(DenseMapInfo<const Value *>::getTombstoneKey(), 0);
}
static unsigned getHashValue(const MemoryLocation &Val) {
return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^
DenseMapInfo<uint64_t>::getHashValue(Val.Size) ^
DenseMapInfo<AAMDNodes>::getHashValue(Val.AATags);
}
static bool isEqual(const MemoryLocation &LHS, const MemoryLocation &RHS) {
return LHS == RHS;
}
};
}
#endif

View File

@ -75,12 +75,12 @@ class PHITransAddr {
bool IsPotentiallyPHITranslatable() const; bool IsPotentiallyPHITranslatable() const;
/// PHITranslateValue - PHI translate the current address up the CFG from /// PHITranslateValue - PHI translate the current address up the CFG from
/// CurBB to Pred, updating our state to reflect any needed changes. If the /// CurBB to Pred, updating our state to reflect any needed changes. If
/// dominator tree DT is non-null, the translated value must dominate /// 'MustDominate' is true, the translated value must dominate
/// PredBB. This returns true on failure and sets Addr to null. /// PredBB. This returns true on failure and sets Addr to null.
bool PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB, bool PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB,
const DominatorTree *DT); const DominatorTree *DT, bool MustDominate);
/// PHITranslateWithInsertion - PHI translate this value into the specified /// PHITranslateWithInsertion - PHI translate this value into the specified
/// predecessor block, inserting a computation of the value if it is /// predecessor block, inserting a computation of the value if it is
/// unavailable. /// unavailable.

View File

@ -221,19 +221,21 @@ class TargetTransformInfo {
/// Parameters that control the generic loop unrolling transformation. /// Parameters that control the generic loop unrolling transformation.
struct UnrollingPreferences { struct UnrollingPreferences {
/// The cost threshold for the unrolled loop, compared to /// The cost threshold for the unrolled loop. Should be relative to the
/// CodeMetrics.NumInsts aggregated over all basic blocks in the loop body. /// getUserCost values returned by this API, and the expectation is that
/// The unrolling factor is set such that the unrolled loop body does not /// the unrolled loop's instructions when run through that interface should
/// exceed this cost. Set this to UINT_MAX to disable the loop body cost /// not exceed this cost. However, this is only an estimate. Also, specific
/// loops may be unrolled even with a cost above this threshold if deemed
/// profitable. Set this to UINT_MAX to disable the loop body cost
/// restriction. /// restriction.
unsigned Threshold; unsigned Threshold;
/// If complete unrolling could help other optimizations (e.g. InstSimplify) /// If complete unrolling will reduce the cost of the loop below its
/// to remove N% of instructions, then we can go beyond unroll threshold. /// expected dynamic cost while rolled by this percentage, apply a discount
/// This value set the minimal percent for allowing that. /// (below) to its unrolled cost.
unsigned MinPercentOfOptimized; unsigned PercentDynamicCostSavedThreshold;
/// The absolute cost threshold. We won't go beyond this even if complete /// The discount applied to the unrolled cost when the *dynamic* cost
/// unrolling could result in optimizing out 90% of instructions. /// savings of unrolling exceed the \c PercentDynamicCostSavedThreshold.
unsigned AbsoluteThreshold; unsigned DynamicCostSavingsDiscount;
/// The cost threshold for the unrolled loop when optimizing for size (set /// The cost threshold for the unrolled loop when optimizing for size (set
/// to UINT_MAX to disable). /// to UINT_MAX to disable).
unsigned OptSizeThreshold; unsigned OptSizeThreshold;
@ -303,7 +305,8 @@ class TargetTransformInfo {
/// mode is legal for a load/store of any legal type. /// mode is legal for a load/store of any legal type.
/// TODO: Handle pre/postinc as well. /// TODO: Handle pre/postinc as well.
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) const; bool HasBaseReg, int64_t Scale,
unsigned AddrSpace = 0) const;
/// \brief Return true if the target works with masked instruction /// \brief Return true if the target works with masked instruction
/// AVX2 allows masks for consecutive load and store for i32 and i64 elements. /// AVX2 allows masks for consecutive load and store for i32 and i64 elements.
@ -319,7 +322,8 @@ class TargetTransformInfo {
/// If the AM is not supported, it returns a negative value. /// If the AM is not supported, it returns a negative value.
/// TODO: Handle pre/postinc as well. /// TODO: Handle pre/postinc as well.
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) const; bool HasBaseReg, int64_t Scale,
unsigned AddrSpace = 0) const;
/// \brief Return true if it's free to truncate a value of type Ty1 to type /// \brief Return true if it's free to truncate a value of type Ty1 to type
/// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16 /// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16
@ -444,6 +448,20 @@ class TargetTransformInfo {
unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) const; unsigned AddressSpace) const;
/// \return The cost of the interleaved memory operation.
/// \p Opcode is the memory operation code
/// \p VecTy is the vector type of the interleaved access.
/// \p Factor is the interleave factor
/// \p Indices is the indices for interleaved load members (as interleaved
/// load allows gaps)
/// \p Alignment is the alignment of the memory operation
/// \p AddressSpace is address space of the pointer.
unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
unsigned Factor,
ArrayRef<unsigned> Indices,
unsigned Alignment,
unsigned AddressSpace) const;
/// \brief Calculate the cost of performing a vector reduction. /// \brief Calculate the cost of performing a vector reduction.
/// ///
/// This is the cost of reducing the vector value of type \p Ty to a scalar /// This is the cost of reducing the vector value of type \p Ty to a scalar
@ -539,12 +557,13 @@ class TargetTransformInfo::Concept {
virtual bool isLegalICmpImmediate(int64_t Imm) = 0; virtual bool isLegalICmpImmediate(int64_t Imm) = 0;
virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset, bool HasBaseReg, int64_t BaseOffset, bool HasBaseReg,
int64_t Scale) = 0; int64_t Scale,
unsigned AddrSpace) = 0;
virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) = 0; virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) = 0;
virtual bool isLegalMaskedLoad(Type *DataType, int Consecutive) = 0; virtual bool isLegalMaskedLoad(Type *DataType, int Consecutive) = 0;
virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset, bool HasBaseReg, int64_t BaseOffset, bool HasBaseReg,
int64_t Scale) = 0; int64_t Scale, unsigned AddrSpace) = 0;
virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0; virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0;
virtual bool isProfitableToHoist(Instruction *I) = 0; virtual bool isProfitableToHoist(Instruction *I) = 0;
virtual bool isTypeLegal(Type *Ty) = 0; virtual bool isTypeLegal(Type *Ty) = 0;
@ -582,6 +601,11 @@ class TargetTransformInfo::Concept {
virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src,
unsigned Alignment, unsigned Alignment,
unsigned AddressSpace) = 0; unsigned AddressSpace) = 0;
virtual unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
unsigned Factor,
ArrayRef<unsigned> Indices,
unsigned Alignment,
unsigned AddressSpace) = 0;
virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, virtual unsigned getReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) = 0; bool IsPairwiseForm) = 0;
virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
@ -648,9 +672,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
return Impl.isLegalICmpImmediate(Imm); return Impl.isLegalICmpImmediate(Imm);
} }
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) override { bool HasBaseReg, int64_t Scale,
unsigned AddrSpace) override {
return Impl.isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, return Impl.isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg,
Scale); Scale, AddrSpace);
} }
bool isLegalMaskedStore(Type *DataType, int Consecutive) override { bool isLegalMaskedStore(Type *DataType, int Consecutive) override {
return Impl.isLegalMaskedStore(DataType, Consecutive); return Impl.isLegalMaskedStore(DataType, Consecutive);
@ -659,8 +684,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
return Impl.isLegalMaskedLoad(DataType, Consecutive); return Impl.isLegalMaskedLoad(DataType, Consecutive);
} }
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) override { bool HasBaseReg, int64_t Scale,
return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg, Scale); unsigned AddrSpace) override {
return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg,
Scale, AddrSpace);
} }
bool isTruncateFree(Type *Ty1, Type *Ty2) override { bool isTruncateFree(Type *Ty1, Type *Ty2) override {
return Impl.isTruncateFree(Ty1, Ty2); return Impl.isTruncateFree(Ty1, Ty2);
@ -740,6 +767,14 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
unsigned AddressSpace) override { unsigned AddressSpace) override {
return Impl.getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace); return Impl.getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
} }
unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
unsigned Factor,
ArrayRef<unsigned> Indices,
unsigned Alignment,
unsigned AddressSpace) override {
return Impl.getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
Alignment, AddressSpace);
}
unsigned getReductionCost(unsigned Opcode, Type *Ty, unsigned getReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) override { bool IsPairwiseForm) override {
return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm); return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm);

View File

@ -207,7 +207,8 @@ class TargetTransformInfoImplBase {
bool isLegalICmpImmediate(int64_t Imm) { return false; } bool isLegalICmpImmediate(int64_t Imm) { return false; }
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) { bool HasBaseReg, int64_t Scale,
unsigned AddrSpace) {
// Guess that only reg and reg+reg addressing is allowed. This heuristic is // Guess that only reg and reg+reg addressing is allowed. This heuristic is
// taken from the implementation of LSR. // taken from the implementation of LSR.
return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1); return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1);
@ -218,9 +219,10 @@ class TargetTransformInfoImplBase {
bool isLegalMaskedLoad(Type *DataType, int Consecutive) { return false; } bool isLegalMaskedLoad(Type *DataType, int Consecutive) { return false; }
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) { bool HasBaseReg, int64_t Scale, unsigned AddrSpace) {
// Guess that all legal addressing mode are free. // Guess that all legal addressing mode are free.
if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale)) if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg,
Scale, AddrSpace))
return 0; return 0;
return -1; return -1;
} }
@ -300,6 +302,14 @@ class TargetTransformInfoImplBase {
return 1; return 1;
} }
unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
unsigned Factor,
ArrayRef<unsigned> Indices,
unsigned Alignment,
unsigned AddressSpace) {
return 1;
}
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys) { ArrayRef<Type *> Tys) {
return 1; return 1;

View File

@ -113,7 +113,7 @@ class BitstreamReader {
return *const_cast<BlockInfo*>(BI); return *const_cast<BlockInfo*>(BI);
// Otherwise, add a new record. // Otherwise, add a new record.
BlockInfoRecords.push_back(BlockInfo()); BlockInfoRecords.emplace_back();
BlockInfoRecords.back().BlockID = BlockID; BlockInfoRecords.back().BlockID = BlockID;
return BlockInfoRecords.back(); return BlockInfoRecords.back();
} }

View File

@ -215,7 +215,7 @@ class BitstreamWriter {
// Push the outer block's abbrev set onto the stack, start out with an // Push the outer block's abbrev set onto the stack, start out with an
// empty abbrev set. // empty abbrev set.
BlockScope.push_back(Block(OldCodeSize, BlockSizeWordIndex)); BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex);
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
// If there is a blockinfo for this BlockID, add all the predefined abbrevs // If there is a blockinfo for this BlockID, add all the predefined abbrevs
@ -503,7 +503,7 @@ class BitstreamWriter {
return *BI; return *BI;
// Otherwise, add a new record. // Otherwise, add a new record.
BlockInfoRecords.push_back(BlockInfo()); BlockInfoRecords.emplace_back();
BlockInfoRecords.back().BlockID = BlockID; BlockInfoRecords.back().BlockID = BlockID;
return BlockInfoRecords.back(); return BlockInfoRecords.back();
} }

View File

@ -125,23 +125,24 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
} }
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) { bool HasBaseReg, int64_t Scale,
unsigned AddrSpace) {
TargetLoweringBase::AddrMode AM; TargetLoweringBase::AddrMode AM;
AM.BaseGV = BaseGV; AM.BaseGV = BaseGV;
AM.BaseOffs = BaseOffset; AM.BaseOffs = BaseOffset;
AM.HasBaseReg = HasBaseReg; AM.HasBaseReg = HasBaseReg;
AM.Scale = Scale; AM.Scale = Scale;
return getTLI()->isLegalAddressingMode(AM, Ty); return getTLI()->isLegalAddressingMode(AM, Ty, AddrSpace);
} }
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) { bool HasBaseReg, int64_t Scale, unsigned AddrSpace) {
TargetLoweringBase::AddrMode AM; TargetLoweringBase::AddrMode AM;
AM.BaseGV = BaseGV; AM.BaseGV = BaseGV;
AM.BaseOffs = BaseOffset; AM.BaseOffs = BaseOffset;
AM.HasBaseReg = HasBaseReg; AM.HasBaseReg = HasBaseReg;
AM.Scale = Scale; AM.Scale = Scale;
return getTLI()->getScalingFactorCost(AM, Ty); return getTLI()->getScalingFactorCost(AM, Ty, AddrSpace);
} }
bool isTruncateFree(Type *Ty1, Type *Ty2) { bool isTruncateFree(Type *Ty1, Type *Ty2) {
@ -522,6 +523,73 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return Cost; return Cost;
} }
unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
unsigned Factor,
ArrayRef<unsigned> Indices,
unsigned Alignment,
unsigned AddressSpace) {
VectorType *VT = dyn_cast<VectorType>(VecTy);
assert(VT && "Expect a vector type for interleaved memory op");
unsigned NumElts = VT->getNumElements();
assert(Factor > 1 && NumElts % Factor == 0 && "Invalid interleave factor");
unsigned NumSubElts = NumElts / Factor;
VectorType *SubVT = VectorType::get(VT->getElementType(), NumSubElts);
// Firstly, the cost of load/store operation.
unsigned Cost = getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace);
// Then plus the cost of interleave operation.
if (Opcode == Instruction::Load) {
// The interleave cost is similar to extract sub vectors' elements
// from the wide vector, and insert them into sub vectors.
//
// E.g. An interleaved load of factor 2 (with one member of index 0):
// %vec = load <8 x i32>, <8 x i32>* %ptr
// %v0 = shuffle %vec, undef, <0, 2, 4, 6> ; Index 0
// The cost is estimated as extract elements at 0, 2, 4, 6 from the
// <8 x i32> vector and insert them into a <4 x i32> vector.
assert(Indices.size() <= Factor &&
"Interleaved memory op has too many members");
for (unsigned Index : Indices) {
assert(Index < Factor && "Invalid index for interleaved memory op");
// Extract elements from loaded vector for each sub vector.
for (unsigned i = 0; i < NumSubElts; i++)
Cost += getVectorInstrCost(Instruction::ExtractElement, VT,
Index + i * Factor);
}
unsigned InsSubCost = 0;
for (unsigned i = 0; i < NumSubElts; i++)
InsSubCost += getVectorInstrCost(Instruction::InsertElement, SubVT, i);
Cost += Indices.size() * InsSubCost;
} else {
// The interleave cost is extract all elements from sub vectors, and
// insert them into the wide vector.
//
// E.g. An interleaved store of factor 2:
// %v0_v1 = shuffle %v0, %v1, <0, 4, 1, 5, 2, 6, 3, 7>
// store <8 x i32> %interleaved.vec, <8 x i32>* %ptr
// The cost is estimated as extract all elements from both <4 x i32>
// vectors and insert into the <8 x i32> vector.
unsigned ExtSubCost = 0;
for (unsigned i = 0; i < NumSubElts; i++)
ExtSubCost += getVectorInstrCost(Instruction::ExtractElement, SubVT, i);
Cost += Factor * ExtSubCost;
for (unsigned i = 0; i < NumElts; i++)
Cost += getVectorInstrCost(Instruction::InsertElement, VT, i);
}
return Cost;
}
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy, unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> Tys) { ArrayRef<Type *> Tys) {
unsigned ISD = 0; unsigned ISD = 0;

View File

@ -24,6 +24,7 @@
#include "llvm/Support/Host.h" #include "llvm/Support/Host.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRecip.h"
#include <string> #include <string>
using namespace llvm; using namespace llvm;
@ -152,6 +153,12 @@ FuseFPOps("fp-contract",
"Only fuse FP ops when the result won't be effected."), "Only fuse FP ops when the result won't be effected."),
clEnumValEnd)); clEnumValEnd));
cl::list<std::string>
ReciprocalOps("recip",
cl::CommaSeparated,
cl::desc("Choose reciprocal operation types and parameters."),
cl::value_desc("all,none,default,divf,!vec-sqrtd,vec-divd:0,sqrt:9..."));
cl::opt<bool> cl::opt<bool>
DontPlaceZerosInBSS("nozero-initialized-in-bss", DontPlaceZerosInBSS("nozero-initialized-in-bss",
cl::desc("Don't place zero-initialized symbols into bss section"), cl::desc("Don't place zero-initialized symbols into bss section"),
@ -230,6 +237,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
TargetOptions Options; TargetOptions Options;
Options.LessPreciseFPMADOption = EnableFPMAD; Options.LessPreciseFPMADOption = EnableFPMAD;
Options.AllowFPOpFusion = FuseFPOps; Options.AllowFPOpFusion = FuseFPOps;
Options.Reciprocals = TargetRecip(ReciprocalOps);
Options.UnsafeFPMath = EnableUnsafeFPMath; Options.UnsafeFPMath = EnableUnsafeFPMath;
Options.NoInfsFPMath = EnableNoInfsFPMath; Options.NoInfsFPMath = EnableNoInfsFPMath;
Options.NoNaNsFPMath = EnableNoNaNsFPMath; Options.NoNaNsFPMath = EnableNoNaNsFPMath;

View File

@ -104,154 +104,14 @@ class DIEAbbrev : public FoldingSetNode {
#endif #endif
}; };
//===--------------------------------------------------------------------===//
/// DIE - A structured debug information entry. Has an abbreviation which
/// describes its organization.
class DIEValue;
class DIE {
protected:
/// Offset - Offset in debug info section.
///
unsigned Offset;
/// Size - Size of instance + children.
///
unsigned Size;
/// Abbrev - Buffer for constructing abbreviation.
///
DIEAbbrev Abbrev;
/// Children DIEs.
///
// This can't be a vector<DIE> because pointer validity is requirent for the
// Parent pointer and DIEEntry.
// It can't be a list<DIE> because some clients need pointer validity before
// the object has been added to any child list
// (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may
// be more convoluted than beneficial.
std::vector<std::unique_ptr<DIE>> Children;
DIE *Parent;
/// Attribute values.
///
SmallVector<DIEValue *, 12> Values;
protected:
DIE()
: Offset(0), Size(0), Abbrev((dwarf::Tag)0, dwarf::DW_CHILDREN_no),
Parent(nullptr) {}
public:
explicit DIE(dwarf::Tag Tag)
: Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no),
Parent(nullptr) {}
// Accessors.
DIEAbbrev &getAbbrev() { return Abbrev; }
const DIEAbbrev &getAbbrev() const { return Abbrev; }
unsigned getAbbrevNumber() const { return Abbrev.getNumber(); }
dwarf::Tag getTag() const { return Abbrev.getTag(); }
unsigned getOffset() const { return Offset; }
unsigned getSize() const { return Size; }
const std::vector<std::unique_ptr<DIE>> &getChildren() const {
return Children;
}
const SmallVectorImpl<DIEValue *> &getValues() const { return Values; }
DIE *getParent() const { return Parent; }
/// Climb up the parent chain to get the compile or type unit DIE this DIE
/// belongs to.
const DIE *getUnit() const;
/// Similar to getUnit, returns null when DIE is not added to an
/// owner yet.
const DIE *getUnitOrNull() const;
void setOffset(unsigned O) { Offset = O; }
void setSize(unsigned S) { Size = S; }
/// addValue - Add a value and attributes to a DIE.
///
void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) {
Abbrev.AddAttribute(Attribute, Form);
Values.push_back(Value);
}
/// addChild - Add a child to the DIE.
///
void addChild(std::unique_ptr<DIE> Child) {
assert(!Child->getParent());
Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
Child->Parent = this;
Children.push_back(std::move(Child));
}
/// findAttribute - Find a value in the DIE with the attribute given,
/// returns NULL if no such attribute exists.
DIEValue *findAttribute(dwarf::Attribute Attribute) const;
#ifndef NDEBUG
void print(raw_ostream &O, unsigned IndentCount = 0) const;
void dump();
#endif
};
//===--------------------------------------------------------------------===//
/// DIEValue - A debug information entry value. Some of these roughly correlate
/// to DWARF attribute classes.
///
class DIEValue {
public:
enum Type {
isInteger,
isString,
isExpr,
isLabel,
isDelta,
isEntry,
isTypeSignature,
isBlock,
isLoc,
isLocList,
};
private:
/// Ty - Type of data stored in the value.
///
Type Ty;
protected:
explicit DIEValue(Type T) : Ty(T) {}
~DIEValue() {}
public:
// Accessors
Type getType() const { return Ty; }
/// EmitValue - Emit value via the Dwarf writer.
///
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
/// SizeOf - Return the size of a value in bytes.
///
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const;
void dump() const;
#endif
};
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// DIEInteger - An integer value DIE. /// DIEInteger - An integer value DIE.
/// ///
class DIEInteger : public DIEValue { class DIEInteger {
friend DIEValue;
uint64_t Integer; uint64_t Integer;
public: public:
explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} explicit DIEInteger(uint64_t I) : Integer(I) {}
/// BestForm - Choose the best form for integer. /// BestForm - Choose the best form for integer.
/// ///
@ -278,120 +138,91 @@ class DIEInteger : public DIEValue {
uint64_t getValue() const { return Integer; } uint64_t getValue() const { return Integer; }
void setValue(uint64_t Val) { Integer = Val; } void setValue(uint64_t Val) { Integer = Val; }
// Implement isa/cast/dyncast. void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
static bool classof(const DIEValue *I) { return I->getType() == isInteger; } unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG #ifndef NDEBUG
void printImpl(raw_ostream &O) const; void print(raw_ostream &O) const;
#endif #endif
}; };
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// DIEExpr - An expression DIE. /// DIEExpr - An expression DIE.
// //
class DIEExpr : public DIEValue { class DIEExpr {
friend class DIEValue;
const MCExpr *Expr; const MCExpr *Expr;
public: public:
explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {} explicit DIEExpr(const MCExpr *E) : Expr(E) {}
/// getValue - Get MCExpr. /// getValue - Get MCExpr.
/// ///
const MCExpr *getValue() const { return Expr; } const MCExpr *getValue() const { return Expr; }
// Implement isa/cast/dyncast. void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
static bool classof(const DIEValue *E) { return E->getType() == isExpr; } unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG #ifndef NDEBUG
void printImpl(raw_ostream &O) const; void print(raw_ostream &O) const;
#endif #endif
}; };
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// DIELabel - A label DIE. /// DIELabel - A label DIE.
// //
class DIELabel : public DIEValue { class DIELabel {
friend class DIEValue;
const MCSymbol *Label; const MCSymbol *Label;
public: public:
explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} explicit DIELabel(const MCSymbol *L) : Label(L) {}
/// getValue - Get MCSymbol. /// getValue - Get MCSymbol.
/// ///
const MCSymbol *getValue() const { return Label; } const MCSymbol *getValue() const { return Label; }
// Implement isa/cast/dyncast. void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
static bool classof(const DIEValue *L) { return L->getType() == isLabel; } unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG #ifndef NDEBUG
void printImpl(raw_ostream &O) const; void print(raw_ostream &O) const;
#endif #endif
}; };
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// DIEDelta - A simple label difference DIE. /// DIEDelta - A simple label difference DIE.
/// ///
class DIEDelta : public DIEValue { class DIEDelta {
friend class DIEValue;
const MCSymbol *LabelHi; const MCSymbol *LabelHi;
const MCSymbol *LabelLo; const MCSymbol *LabelLo;
public: public:
DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) : LabelHi(Hi), LabelLo(Lo) {}
: DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
// Implement isa/cast/dyncast. void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
static bool classof(const DIEValue *D) { return D->getType() == isDelta; } unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG #ifndef NDEBUG
void printImpl(raw_ostream &O) const; void print(raw_ostream &O) const;
#endif #endif
}; };
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// DIEString - A container for string values. /// DIEString - A container for string values.
/// ///
class DIEString : public DIEValue { class DIEString {
friend class DIEValue;
DwarfStringPoolEntryRef S; DwarfStringPoolEntryRef S;
public: public:
DIEString(DwarfStringPoolEntryRef S) : DIEValue(isString), S(S) {} DIEString(DwarfStringPoolEntryRef S) : S(S) {}
/// getString - Grab the string out of the object. /// getString - Grab the string out of the object.
StringRef getString() const { return S.getString(); } StringRef getString() const { return S.getString(); }
// Implement isa/cast/dyncast. void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
static bool classof(const DIEValue *D) { return D->getType() == isString; } unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG #ifndef NDEBUG
void printImpl(raw_ostream &O) const; void print(raw_ostream &O) const;
#endif #endif
}; };
@ -399,72 +230,350 @@ class DIEString : public DIEValue {
/// DIEEntry - A pointer to another debug information entry. An instance of /// DIEEntry - A pointer to another debug information entry. An instance of
/// this class can also be used as a proxy for a debug information entry not /// this class can also be used as a proxy for a debug information entry not
/// yet defined (ie. types.) /// yet defined (ie. types.)
class DIEEntry : public DIEValue { class DIE;
friend class DIEValue; class DIEEntry {
DIE *Entry;
DIE &Entry; DIEEntry() = delete;
public: public:
explicit DIEEntry(DIE &E) : DIEValue(isEntry), Entry(E) { explicit DIEEntry(DIE &E) : Entry(&E) {}
}
DIE &getEntry() const { return Entry; } DIE &getEntry() const { return *Entry; }
/// Returns size of a ref_addr entry. /// Returns size of a ref_addr entry.
static unsigned getRefAddrSize(const AsmPrinter *AP); static unsigned getRefAddrSize(const AsmPrinter *AP);
// Implement isa/cast/dyncast. void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
static bool classof(const DIEValue *E) { return E->getType() == isEntry; } unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const {
return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP)
: sizeof(int32_t); : sizeof(int32_t);
} }
#ifndef NDEBUG #ifndef NDEBUG
void printImpl(raw_ostream &O) const; void print(raw_ostream &O) const;
#endif #endif
}; };
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// \brief A signature reference to a type unit. /// \brief A signature reference to a type unit.
class DIETypeSignature : public DIEValue { class DIETypeSignature {
friend class DIEValue; const DwarfTypeUnit *Unit;
const DwarfTypeUnit &Unit; DIETypeSignature() = delete;
public: public:
explicit DIETypeSignature(const DwarfTypeUnit &Unit) explicit DIETypeSignature(const DwarfTypeUnit &Unit) : Unit(&Unit) {}
: DIEValue(isTypeSignature), Unit(Unit) {}
// \brief Implement isa/cast/dyncast. void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
static bool classof(const DIEValue *E) { unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
return E->getType() == isTypeSignature;
}
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const {
assert(Form == dwarf::DW_FORM_ref_sig8); assert(Form == dwarf::DW_FORM_ref_sig8);
return 8; return 8;
} }
#ifndef NDEBUG #ifndef NDEBUG
void printImpl(raw_ostream &O) const; void print(raw_ostream &O) const;
#endif
};
//===--------------------------------------------------------------------===//
/// DIELocList - Represents a pointer to a location list in the debug_loc
/// section.
//
class DIELocList {
// Index into the .debug_loc vector.
size_t Index;
public:
DIELocList(size_t I) : Index(I) {}
/// getValue - Grab the current index out.
size_t getValue() const { return Index; }
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const;
#endif
};
//===--------------------------------------------------------------------===//
/// DIEValue - A debug information entry value. Some of these roughly correlate
/// to DWARF attribute classes.
///
class DIEBlock;
class DIELoc;
class DIEValue {
public:
enum Type {
isNone,
#define HANDLE_DIEVALUE(T) is##T,
#include "llvm/CodeGen/DIEValue.def"
};
private:
/// Ty - Type of data stored in the value.
///
Type Ty = isNone;
dwarf::Attribute Attribute = (dwarf::Attribute)0;
dwarf::Form Form = (dwarf::Form)0;
/// Storage for the value.
///
/// All values that aren't standard layout (or are larger than 8 bytes)
/// should be stored by reference instead of by value.
typedef AlignedCharArrayUnion<DIEInteger, DIEString, DIEExpr, DIELabel,
DIEDelta *, DIEEntry, DIETypeSignature,
DIEBlock *, DIELoc *, DIELocList> ValTy;
static_assert(sizeof(ValTy) <= sizeof(uint64_t) ||
sizeof(ValTy) <= sizeof(void *),
"Expected all large types to be stored via pointer");
/// Underlying stored value.
ValTy Val;
template <class T> void construct(T V) {
static_assert(std::is_standard_layout<T>::value ||
std::is_pointer<T>::value,
"Expected standard layout or pointer");
new (reinterpret_cast<void *>(Val.buffer)) T(V);
}
template <class T> T *get() { return reinterpret_cast<T *>(Val.buffer); }
template <class T> const T *get() const {
return reinterpret_cast<const T *>(Val.buffer);
}
template <class T> void destruct() { get<T>()->~T(); }
/// Destroy the underlying value.
///
/// This should get optimized down to a no-op. We could skip it if we could
/// add a static assert on \a std::is_trivially_copyable(), but we currently
/// support versions of GCC that don't understand that.
void destroyVal() {
switch (Ty) {
case isNone:
return;
#define HANDLE_DIEVALUE_SMALL(T) \
case is##T: \
destruct<DIE##T>();
return;
#define HANDLE_DIEVALUE_LARGE(T) \
case is##T: \
destruct<const DIE##T *>();
return;
#include "llvm/CodeGen/DIEValue.def"
}
}
/// Copy the underlying value.
///
/// This should get optimized down to a simple copy. We need to actually
/// construct the value, rather than calling memcpy, to satisfy strict
/// aliasing rules.
void copyVal(const DIEValue &X) {
switch (Ty) {
case isNone:
return;
#define HANDLE_DIEVALUE_SMALL(T) \
case is##T: \
construct<DIE##T>(*X.get<DIE##T>()); \
return;
#define HANDLE_DIEVALUE_LARGE(T) \
case is##T: \
construct<const DIE##T *>(*X.get<const DIE##T *>()); \
return;
#include "llvm/CodeGen/DIEValue.def"
}
}
public:
DIEValue() = default;
DIEValue(const DIEValue &X) : Ty(X.Ty), Attribute(X.Attribute), Form(X.Form) {
copyVal(X);
}
DIEValue &operator=(const DIEValue &X) {
destroyVal();
Ty = X.Ty;
Attribute = X.Attribute;
Form = X.Form;
copyVal(X);
return *this;
}
~DIEValue() { destroyVal(); }
#define HANDLE_DIEVALUE_SMALL(T) \
DIEValue(dwarf::Attribute Attribute, dwarf::Form Form, const DIE##T &V) \
: Ty(is##T), Attribute(Attribute), Form(Form) { \
construct<DIE##T>(V); \
}
#define HANDLE_DIEVALUE_LARGE(T) \
DIEValue(dwarf::Attribute Attribute, dwarf::Form Form, const DIE##T *V) \
: Ty(is##T), Attribute(Attribute), Form(Form) { \
assert(V && "Expected valid value"); \
construct<const DIE##T *>(V); \
}
#include "llvm/CodeGen/DIEValue.def"
// Accessors
Type getType() const { return Ty; }
dwarf::Attribute getAttribute() const { return Attribute; }
dwarf::Form getForm() const { return Form; }
explicit operator bool() const { return Ty; }
#define HANDLE_DIEVALUE_SMALL(T) \
const DIE##T &getDIE##T() const { \
assert(getType() == is##T && "Expected " #T); \
return *get<DIE##T>(); \
}
#define HANDLE_DIEVALUE_LARGE(T) \
const DIE##T &getDIE##T() const { \
assert(getType() == is##T && "Expected " #T); \
return **get<const DIE##T *>(); \
}
#include "llvm/CodeGen/DIEValue.def"
/// EmitValue - Emit value via the Dwarf writer.
///
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
/// SizeOf - Return the size of a value in bytes.
///
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const;
void dump() const;
#endif
};
//===--------------------------------------------------------------------===//
/// DIE - A structured debug information entry. Has an abbreviation which
/// describes its organization.
class DIE {
protected:
/// Offset - Offset in debug info section.
///
unsigned Offset;
/// Size - Size of instance + children.
///
unsigned Size;
unsigned AbbrevNumber = ~0u;
/// Tag - Dwarf tag code.
///
dwarf::Tag Tag = (dwarf::Tag)0;
/// Children DIEs.
///
// This can't be a vector<DIE> because pointer validity is requirent for the
// Parent pointer and DIEEntry.
// It can't be a list<DIE> because some clients need pointer validity before
// the object has been added to any child list
// (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may
// be more convoluted than beneficial.
std::vector<std::unique_ptr<DIE>> Children;
DIE *Parent;
/// Attribute values.
///
SmallVector<DIEValue, 12> Values;
protected:
DIE() : Offset(0), Size(0), Parent(nullptr) {}
public:
explicit DIE(dwarf::Tag Tag)
: Offset(0), Size(0), Tag(Tag), Parent(nullptr) {}
// Accessors.
unsigned getAbbrevNumber() const { return AbbrevNumber; }
dwarf::Tag getTag() const { return Tag; }
unsigned getOffset() const { return Offset; }
unsigned getSize() const { return Size; }
bool hasChildren() const { return !Children.empty(); }
typedef std::vector<std::unique_ptr<DIE>>::const_iterator child_iterator;
typedef iterator_range<child_iterator> child_range;
child_range children() const {
return llvm::make_range(Children.begin(), Children.end());
}
typedef SmallVectorImpl<DIEValue>::const_iterator value_iterator;
typedef iterator_range<value_iterator> value_range;
value_iterator values_begin() const { return Values.begin(); }
value_iterator values_end() const { return Values.end(); }
value_range values() const {
return llvm::make_range(values_begin(), values_end());
}
void setValue(unsigned I, DIEValue New) {
assert(I < Values.size());
Values[I] = New;
}
DIE *getParent() const { return Parent; }
/// Generate the abbreviation for this DIE.
///
/// Calculate the abbreviation for this, which should be uniqued and
/// eventually used to call \a setAbbrevNumber().
DIEAbbrev generateAbbrev() const;
/// Set the abbreviation number for this DIE.
void setAbbrevNumber(unsigned I) { AbbrevNumber = I; }
/// Climb up the parent chain to get the compile or type unit DIE this DIE
/// belongs to.
const DIE *getUnit() const;
/// Similar to getUnit, returns null when DIE is not added to an
/// owner yet.
const DIE *getUnitOrNull() const;
void setOffset(unsigned O) { Offset = O; }
void setSize(unsigned S) { Size = S; }
/// addValue - Add a value and attributes to a DIE.
///
void addValue(DIEValue Value) { Values.push_back(Value); }
template <class T>
void addValue(dwarf::Attribute Attribute, dwarf::Form Form, T &&Value) {
Values.emplace_back(Attribute, Form, std::forward<T>(Value));
}
/// addChild - Add a child to the DIE.
///
DIE &addChild(std::unique_ptr<DIE> Child) {
assert(!Child->getParent());
Child->Parent = this;
Children.push_back(std::move(Child));
return *Children.back();
}
/// Find a value in the DIE with the attribute given.
///
/// Returns a default-constructed DIEValue (where \a DIEValue::getType()
/// gives \a DIEValue::isNone) if no such attribute exists.
DIEValue findAttribute(dwarf::Attribute Attribute) const;
#ifndef NDEBUG
void print(raw_ostream &O, unsigned IndentCount = 0) const;
void dump();
#endif #endif
}; };
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// DIELoc - Represents an expression location. /// DIELoc - Represents an expression location.
// //
class DIELoc : public DIEValue, public DIE { class DIELoc : public DIE {
friend class DIEValue;
mutable unsigned Size; // Size in bytes excluding size header. mutable unsigned Size; // Size in bytes excluding size header.
public: public:
DIELoc() : DIEValue(isLoc), Size(0) {} DIELoc() : Size(0) {}
/// ComputeSize - Calculate the size of the location expression. /// ComputeSize - Calculate the size of the location expression.
/// ///
@ -485,27 +594,22 @@ class DIELoc : public DIEValue, public DIE {
return dwarf::DW_FORM_block; return dwarf::DW_FORM_block;
} }
// Implement isa/cast/dyncast. void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
static bool classof(const DIEValue *E) { return E->getType() == isLoc; } unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG #ifndef NDEBUG
void printImpl(raw_ostream &O) const; void print(raw_ostream &O) const;
#endif #endif
}; };
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// DIEBlock - Represents a block of values. /// DIEBlock - Represents a block of values.
// //
class DIEBlock : public DIEValue, public DIE { class DIEBlock : public DIE {
friend class DIEValue;
mutable unsigned Size; // Size in bytes excluding size header. mutable unsigned Size; // Size in bytes excluding size header.
public: public:
DIEBlock() : DIEValue(isBlock), Size(0) {} DIEBlock() : Size(0) {}
/// ComputeSize - Calculate the size of the location expression. /// ComputeSize - Calculate the size of the location expression.
/// ///
@ -523,43 +627,11 @@ class DIEBlock : public DIEValue, public DIE {
return dwarf::DW_FORM_block; return dwarf::DW_FORM_block;
} }
// Implement isa/cast/dyncast. void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
static bool classof(const DIEValue *E) { return E->getType() == isBlock; } unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG #ifndef NDEBUG
void printImpl(raw_ostream &O) const; void print(raw_ostream &O) const;
#endif
};
//===--------------------------------------------------------------------===//
/// DIELocList - Represents a pointer to a location list in the debug_loc
/// section.
//
class DIELocList : public DIEValue {
friend class DIEValue;
// Index into the .debug_loc vector.
size_t Index;
public:
DIELocList(size_t I) : DIEValue(isLocList), Index(I) {}
/// getValue - Grab the current index out.
size_t getValue() const { return Index; }
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *E) { return E->getType() == isLocList; }
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void printImpl(raw_ostream &O) const;
#endif #endif
}; };

View File

@ -0,0 +1,47 @@
//===- llvm/CodeGen/DIEValue.def - DIEValue types ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Macros for running through all types of DIEValue.
//
//===----------------------------------------------------------------------===//
#if !(defined HANDLE_DIEVALUE || defined HANDLE_DIEVALUE_SMALL || \
defined HANDLE_DIEVALUE_LARGE)
#error "Missing macro definition of HANDLE_DIEVALUE"
#endif
// Handler for all values.
#ifndef HANDLE_DIEVALUE
#define HANDLE_DIEVALUE(T)
#endif
// Handler for small values.
#ifndef HANDLE_DIEVALUE_SMALL
#define HANDLE_DIEVALUE_SMALL(T) HANDLE_DIEVALUE(T)
#endif
// Handler for large values.
#ifndef HANDLE_DIEVALUE_LARGE
#define HANDLE_DIEVALUE_LARGE(T) HANDLE_DIEVALUE(T)
#endif
HANDLE_DIEVALUE_SMALL(Integer)
HANDLE_DIEVALUE_SMALL(String)
HANDLE_DIEVALUE_SMALL(Expr)
HANDLE_DIEVALUE_SMALL(Label)
HANDLE_DIEVALUE_LARGE(Delta)
HANDLE_DIEVALUE_SMALL(Entry)
HANDLE_DIEVALUE_SMALL(TypeSignature)
HANDLE_DIEVALUE_LARGE(Block)
HANDLE_DIEVALUE_LARGE(Loc)
HANDLE_DIEVALUE_SMALL(LocList)
#undef HANDLE_DIEVALUE
#undef HANDLE_DIEVALUE_SMALL
#undef HANDLE_DIEVALUE_LARGE

View File

@ -121,7 +121,7 @@ class GCFunctionInfo {
/// label just prior to the safe point (if the code generator is using /// label just prior to the safe point (if the code generator is using
/// MachineModuleInfo). /// MachineModuleInfo).
void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) {
SafePoints.push_back(GCPoint(Kind, Label, DL)); SafePoints.emplace_back(Kind, Label, DL);
} }
/// getFrameSize/setFrameSize - Records the function's frame size. /// getFrameSize/setFrameSize - Records the function's frame size.

View File

@ -102,6 +102,10 @@ class LiveRangeEdit : private MachineRegisterInfo::Delegate {
/// registers are created. /// registers are created.
void MRI_NoteNewVirtualRegister(unsigned VReg) override; void MRI_NoteNewVirtualRegister(unsigned VReg) override;
/// \brief Check if MachineOperand \p MO is a last use/kill either in the
/// main live range of \p LI or in one of the matching subregister ranges.
bool useIsKill(const LiveInterval &LI, const MachineOperand &MO) const;
public: public:
/// Create a LiveRangeEdit for breaking down parent into smaller pieces. /// Create a LiveRangeEdit for breaking down parent into smaller pieces.
/// @param parent The register being spilled or split. /// @param parent The register being spilled or split.

View File

@ -0,0 +1,52 @@
//===- MIRParser.h - MIR serialization format parser ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This MIR serialization library is currently a work in progress. It can't
// serialize machine functions at this time.
//
// This file declares the functions that parse the MIR serialization format
// files.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_MIRPARSER_MIRPARSER_H
#define LLVM_CODEGEN_MIRPARSER_MIRPARSER_H
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
#include <memory>
namespace llvm {
class SMDiagnostic;
/// This function is the main interface to the MIR serialization format parser.
///
/// It reads a YAML file that has an optional LLVM IR and returns an LLVM
/// module.
/// \param Filename - The name of the file to parse.
/// \param Error - Error result info.
/// \param Context - Context in which to allocate globals info.
std::unique_ptr<Module> parseMIRFile(StringRef Filename, SMDiagnostic &Error,
LLVMContext &Context);
/// This function is another interface to the MIR serialization format parser.
///
/// It parses the optional LLVM IR in the given buffer, and returns an LLVM
/// module.
/// \param Contents - The MemoryBuffer containing the machine level IR.
/// \param Error - Error result info.
/// \param Context - Context in which to allocate globals info.
std::unique_ptr<Module> parseMIR(std::unique_ptr<MemoryBuffer> Contents,
SMDiagnostic &Error, LLVMContext &Context);
} // end namespace llvm
#endif

View File

@ -0,0 +1,40 @@
//===- MIRYAMLMapping.h - Describes the mapping between MIR and YAML ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The MIR serialization library is currently a work in progress. It can't
// serialize machine functions at this time.
//
// This file implements the mapping between various MIR data structures and
// their corresponding YAML representation.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
#define LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/YAMLTraits.h"
namespace llvm {
namespace yaml {
struct MachineFunction {
StringRef Name;
};
template <> struct MappingTraits<MachineFunction> {
static void mapping(IO &YamlIO, MachineFunction &MF) {
YamlIO.mapRequired("name", MF.Name);
}
};
} // end namespace yaml
} // end namespace llvm
#endif

View File

@ -256,11 +256,6 @@ class MachineFrameInfo {
/// Not null, if shrink-wrapping found a better place for the epilogue. /// Not null, if shrink-wrapping found a better place for the epilogue.
MachineBasicBlock *Restore; MachineBasicBlock *Restore;
/// Check if it exists a path from \p MBB leading to the basic
/// block with a SavePoint (a.k.a. prologue).
bool isBeforeSavePoint(const MachineFunction &MF,
const MachineBasicBlock &MBB) const;
public: public:
explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign, explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign,
bool RealignOpt) bool RealignOpt)
@ -627,16 +622,15 @@ class MachineFrameInfo {
MachineBasicBlock *getRestorePoint() const { return Restore; } MachineBasicBlock *getRestorePoint() const { return Restore; }
void setRestorePoint(MachineBasicBlock *NewRestore) { Restore = NewRestore; } void setRestorePoint(MachineBasicBlock *NewRestore) { Restore = NewRestore; }
/// getPristineRegs - Return a set of physical registers that are pristine on /// Return a set of physical registers that are pristine.
/// entry to the MBB.
/// ///
/// Pristine registers hold a value that is useless to the current function, /// Pristine registers hold a value that is useless to the current function,
/// but that must be preserved - they are callee saved registers that have not /// but that must be preserved - they are callee saved registers that are not
/// been saved yet. /// saved.
/// ///
/// Before the PrologueEpilogueInserter has placed the CSR spill code, this /// Before the PrologueEpilogueInserter has placed the CSR spill code, this
/// method always returns an empty set. /// method always returns an empty set.
BitVector getPristineRegs(const MachineBasicBlock *MBB) const; BitVector getPristineRegs(const MachineFunction &MF) const;
/// print - Used by the MachineFunction printer to print information about /// print - Used by the MachineFunction printer to print information about
/// stack objects. Implemented in MachineFunction.cpp /// stack objects. Implemented in MachineFunction.cpp

View File

@ -331,6 +331,11 @@ class MachineInstr : public ilist_node<MachineInstr> {
operands_begin() + getDesc().getNumDefs(), operands_end()); operands_begin() + getDesc().getNumDefs(), operands_end());
} }
/// Returns the number of the operand iterator \p I points to.
unsigned getOperandNo(const_mop_iterator I) const {
return I - operands_begin();
}
/// Access to memory operands of the instruction /// Access to memory operands of the instruction
mmo_iterator memoperands_begin() const { return MemRefs; } mmo_iterator memoperands_begin() const { return MemRefs; }
mmo_iterator memoperands_end() const { return MemRefs + NumMemRefs; } mmo_iterator memoperands_end() const { return MemRefs + NumMemRefs; }
@ -483,6 +488,13 @@ class MachineInstr : public ilist_node<MachineInstr> {
return hasProperty(MCID::NotDuplicable, Type); return hasProperty(MCID::NotDuplicable, Type);
} }
/// Return true if this instruction is convergent.
/// Convergent instructions can only be moved to locations that are
/// control-equivalent to their initial position.
bool isConvergent(QueryType Type = AnyInBundle) const {
return hasProperty(MCID::Convergent, Type);
}
/// Returns true if the specified instruction has a delay slot /// Returns true if the specified instruction has a delay slot
/// which must be filled by the code generator. /// which must be filled by the code generator.
bool hasDelaySlot(QueryType Type = AnyInBundle) const { bool hasDelaySlot(QueryType Type = AnyInBundle) const {
@ -924,7 +936,7 @@ class MachineInstr : public ilist_node<MachineInstr> {
/// For normal instructions, this is derived from the MCInstrDesc. /// For normal instructions, this is derived from the MCInstrDesc.
/// For inline assembly it is derived from the flag words. /// For inline assembly it is derived from the flag words.
/// ///
/// Returns NULL if the static register classs constraint cannot be /// Returns NULL if the static register class constraint cannot be
/// determined. /// determined.
/// ///
const TargetRegisterClass* const TargetRegisterClass*
@ -936,10 +948,10 @@ class MachineInstr : public ilist_node<MachineInstr> {
/// the given \p CurRC. /// the given \p CurRC.
/// If \p ExploreBundle is set and MI is part of a bundle, all the /// If \p ExploreBundle is set and MI is part of a bundle, all the
/// instructions inside the bundle will be taken into account. In other words, /// instructions inside the bundle will be taken into account. In other words,
/// this method accumulates all the constrains of the operand of this MI and /// this method accumulates all the constraints of the operand of this MI and
/// the related bundle if MI is a bundle or inside a bundle. /// the related bundle if MI is a bundle or inside a bundle.
/// ///
/// Returns the register class that statisfies both \p CurRC and the /// Returns the register class that satisfies both \p CurRC and the
/// constraints set by MI. Returns NULL if such a register class does not /// constraints set by MI. Returns NULL if such a register class does not
/// exist. /// exist.
/// ///
@ -952,7 +964,7 @@ class MachineInstr : public ilist_node<MachineInstr> {
/// \brief Applies the constraints (def/use) implied by the \p OpIdx operand /// \brief Applies the constraints (def/use) implied by the \p OpIdx operand
/// to the given \p CurRC. /// to the given \p CurRC.
/// ///
/// Returns the register class that statisfies both \p CurRC and the /// Returns the register class that satisfies both \p CurRC and the
/// constraints set by \p OpIdx MI. Returns NULL if such a register class /// constraints set by \p OpIdx MI. Returns NULL if such a register class
/// does not exist. /// does not exist.
/// ///

View File

@ -114,7 +114,7 @@ class MachineLoopInfo : public MachineFunctionPass {
} }
// isLoopHeader - True if the block is a loop header node // isLoopHeader - True if the block is a loop header node
inline bool isLoopHeader(MachineBasicBlock *BB) const { inline bool isLoopHeader(const MachineBasicBlock *BB) const {
return LI.isLoopHeader(BB); return LI.isLoopHeader(BB);
} }

View File

@ -17,11 +17,11 @@
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
#include <functional>
#include <string> #include <string>
namespace llvm { namespace llvm {
class FunctionPass;
class MachineFunctionPass; class MachineFunctionPass;
class PassConfigImpl; class PassConfigImpl;
class PassInfo; class PassInfo;
@ -374,6 +374,10 @@ namespace llvm {
createMachineFunctionPrinterPass(raw_ostream &OS, createMachineFunctionPrinterPass(raw_ostream &OS,
const std::string &Banner =""); const std::string &Banner ="");
/// MIRPrinting pass - this pass prints out the LLVM IR into the given stream
/// using the MIR serialization format.
MachineFunctionPass *createPrintMIRPass(raw_ostream &OS);
/// createCodeGenPreparePass - Transform the code to expose more pattern /// createCodeGenPreparePass - Transform the code to expose more pattern
/// matching during instruction selection. /// matching during instruction selection.
FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr); FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr);
@ -488,6 +492,10 @@ namespace llvm {
/// MachineFunctionPrinterPass - This pass prints out MachineInstr's. /// MachineFunctionPrinterPass - This pass prints out MachineInstr's.
extern char &MachineFunctionPrinterPassID; extern char &MachineFunctionPrinterPassID;
/// MIRPrintingPass - this pass prints out the LLVM IR using the MIR
/// serialization format.
extern char &MIRPrintingPassID;
/// TailDuplicate - Duplicate blocks with unconditional branches /// TailDuplicate - Duplicate blocks with unconditional branches
/// into tails of their predecessors. /// into tails of their predecessors.
extern char &TailDuplicateID; extern char &TailDuplicateID;
@ -511,6 +519,8 @@ namespace llvm {
/// IfConverter - This pass performs machine code if conversion. /// IfConverter - This pass performs machine code if conversion.
extern char &IfConverterID; extern char &IfConverterID;
FunctionPass *createIfConverter(std::function<bool(const Function &)> Ftor);
/// MachineBlockPlacement - This pass places basic blocks based on branch /// MachineBlockPlacement - This pass places basic blocks based on branch
/// probabilities. /// probabilities.
extern char &MachineBlockPlacementID; extern char &MachineBlockPlacementID;
@ -605,6 +615,9 @@ namespace llvm {
/// UnpackMachineBundles - This pass unpack machine instruction bundles. /// UnpackMachineBundles - This pass unpack machine instruction bundles.
extern char &UnpackMachineBundlesID; extern char &UnpackMachineBundlesID;
FunctionPass *
createUnpackMachineBundles(std::function<bool(const Function &)> Ftor);
/// FinalizeMachineBundles - This pass finalize machine instruction /// FinalizeMachineBundles - This pass finalize machine instruction
/// bundles (created earlier, e.g. during pre-RA scheduling). /// bundles (created earlier, e.g. during pre-RA scheduling).
extern char &FinalizeMachineBundlesID; extern char &FinalizeMachineBundlesID;

View File

@ -260,7 +260,7 @@ namespace llvm {
#ifndef NDEBUG #ifndef NDEBUG
const SUnit *Addr = SUnits.empty() ? nullptr : &SUnits[0]; const SUnit *Addr = SUnits.empty() ? nullptr : &SUnits[0];
#endif #endif
SUnits.push_back(SUnit(MI, (unsigned)SUnits.size())); SUnits.emplace_back(MI, (unsigned)SUnits.size());
assert((Addr == nullptr || Addr == &SUnits[0]) && assert((Addr == nullptr || Addr == &SUnits[0]) &&
"SUnits std::vector reallocated on the fly!"); "SUnits std::vector reallocated on the fly!");
SUnits.back().OrigNode = &SUnits.back(); SUnits.back().OrigNode = &SUnits.back();

View File

@ -878,6 +878,10 @@ class SelectionDAG {
/// Return an MDNodeSDNode which holds an MDNode. /// Return an MDNodeSDNode which holds an MDNode.
SDValue getMDNode(const MDNode *MD); SDValue getMDNode(const MDNode *MD);
/// Return a bitcast using the SDLoc of the value operand, and casting to the
/// provided type. Use getNode to set a custom SDLoc.
SDValue getBitcast(EVT VT, SDValue V);
/// Return an AddrSpaceCastSDNode. /// Return an AddrSpaceCastSDNode.
SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr, SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr,
unsigned SrcAS, unsigned DestAS); unsigned SrcAS, unsigned DestAS);

View File

@ -23,6 +23,7 @@ class BasicBlock;
class Constant; class Constant;
class Function; class Function;
class GlobalVariable; class GlobalVariable;
class InvokeInst;
class IntrinsicInst; class IntrinsicInst;
class LandingPadInst; class LandingPadInst;
class MCSymbol; class MCSymbol;
@ -153,5 +154,11 @@ struct WinEHFuncInfo {
NumIPToStateFuncsVisited(0) {} NumIPToStateFuncsVisited(0) {}
}; };
/// Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which
/// describes the state numbers and tables used by __CxxFrameHandler3. This
/// analysis assumes that WinEHPrepare has already been run.
void calculateWinCXXEHStateNumbers(const Function *ParentFn,
WinEHFuncInfo &FuncInfo);
} }
#endif // LLVM_CODEGEN_WINEHFUNCINFO_H #endif // LLVM_CODEGEN_WINEHFUNCINFO_H

View File

@ -141,8 +141,7 @@ class DIContext {
/// on the fly. /// on the fly.
class LoadedObjectInfo { class LoadedObjectInfo {
public: public:
LoadedObjectInfo() {} virtual ~LoadedObjectInfo() = default;
virtual ~LoadedObjectInfo() {}
/// Obtain the Load Address of a section by Name. /// Obtain the Load Address of a section by Name.
/// ///
@ -170,7 +169,7 @@ class LoadedObjectInfo {
/// Obtain a copy of this LoadedObjectInfo. /// Obtain a copy of this LoadedObjectInfo.
/// ///
/// The caller is responsible for deallocation once the copy is no longer required. /// The caller is responsible for deallocation once the copy is no longer required.
virtual LoadedObjectInfo *clone() const = 0; virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0;
}; };
} }

View File

@ -38,12 +38,12 @@ class DWARFDebugLine {
// The size in bytes of the statement information for this compilation unit // The size in bytes of the statement information for this compilation unit
// (not including the total_length field itself). // (not including the total_length field itself).
uint32_t TotalLength; uint64_t TotalLength;
// Version identifier for the statement information format. // Version identifier for the statement information format.
uint16_t Version; uint16_t Version;
// The number of bytes following the prologue_length field to the beginning // The number of bytes following the prologue_length field to the beginning
// of the first byte of the statement program itself. // of the first byte of the statement program itself.
uint32_t PrologueLength; uint64_t PrologueLength;
// The size in bytes of the smallest target machine instruction. Statement // The size in bytes of the smallest target machine instruction. Statement
// program opcodes that alter the address register first multiply their // program opcodes that alter the address register first multiply their
// operands by this value. // operands by this value.
@ -63,14 +63,22 @@ class DWARFDebugLine {
std::vector<const char*> IncludeDirectories; std::vector<const char*> IncludeDirectories;
std::vector<FileNameEntry> FileNames; std::vector<FileNameEntry> FileNames;
bool IsDWARF64;
uint32_t sizeofTotalLength() const {
return IsDWARF64 ? 12 : 4;
}
uint32_t sizeofPrologueLength() const {
return IsDWARF64 ? 8 : 4;
}
// Length of the prologue in bytes. // Length of the prologue in bytes.
uint32_t getLength() const { uint32_t getLength() const {
return PrologueLength + sizeof(TotalLength) + sizeof(Version) + return PrologueLength + sizeofTotalLength() + sizeof(Version) +
sizeof(PrologueLength); sizeofPrologueLength();
} }
// Length of the line table data in bytes (not including the prologue). // Length of the line table data in bytes (not including the prologue).
uint32_t getStatementTableLength() const { uint32_t getStatementTableLength() const {
return TotalLength + sizeof(TotalLength) - getLength(); return TotalLength + sizeofTotalLength() - getLength();
} }
int32_t getMaxLineIncrementForSpecialOpcode() const { int32_t getMaxLineIncrementForSpecialOpcode() const {
return LineBase + (int8_t)LineRange - 1; return LineBase + (int8_t)LineRange - 1;
@ -163,6 +171,9 @@ class DWARFDebugLine {
struct LineTable { struct LineTable {
LineTable(); LineTable();
// Represents an invalid row
const uint32_t UnknownRowIndex = UINT32_MAX;
void appendRow(const DWARFDebugLine::Row &R) { void appendRow(const DWARFDebugLine::Row &R) {
Rows.push_back(R); Rows.push_back(R);
} }
@ -171,7 +182,7 @@ class DWARFDebugLine {
} }
// Returns the index of the row with file/line info for a given address, // Returns the index of the row with file/line info for a given address,
// or -1 if there is no such row. // or UnknownRowIndex if there is no such row.
uint32_t lookupAddress(uint64_t address) const; uint32_t lookupAddress(uint64_t address) const;
bool lookupAddressRange(uint64_t address, uint64_t size, bool lookupAddressRange(uint64_t address, uint64_t size,
@ -203,6 +214,10 @@ class DWARFDebugLine {
typedef SequenceVector::const_iterator SequenceIter; typedef SequenceVector::const_iterator SequenceIter;
RowVector Rows; RowVector Rows;
SequenceVector Sequences; SequenceVector Sequences;
private:
uint32_t findRowInSeq(const DWARFDebugLine::Sequence &seq,
uint64_t address) const;
}; };
const LineTable *getLineTable(uint32_t offset) const; const LineTable *getLineTable(uint32_t offset) const;

View File

@ -390,8 +390,7 @@ class CompileOnDemandLayer {
for (auto &F : *M) { for (auto &F : *M) {
if (F.isDeclaration()) if (F.isDeclaration())
continue; continue;
Partitioning.push_back(std::vector<Function*>()); Partitioning.emplace_back(1, &F);
Partitioning.back().push_back(&F);
} }
addLogicalModule(*LogicalDylibs.back(), addLogicalModule(*LogicalDylibs.back(),
std::shared_ptr<Module>(std::move(M)), std::shared_ptr<Module>(std::move(M)),

View File

@ -15,6 +15,7 @@
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H #define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H
#include "JITSymbolFlags.h" #include "JITSymbolFlags.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Support/Memory.h" #include "llvm/Support/Memory.h"
#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DIContext.h"
@ -62,8 +63,6 @@ class RuntimeDyld {
unsigned EndIdx) unsigned EndIdx)
: RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { } : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { }
virtual ~LoadedObjectInfo() = default;
virtual object::OwningBinary<object::ObjectFile> virtual object::OwningBinary<object::ObjectFile>
getObjectForDebug(const object::ObjectFile &Obj) const = 0; getObjectForDebug(const object::ObjectFile &Obj) const = 0;
@ -80,8 +79,8 @@ class RuntimeDyld {
LoadedObjectInfoHelper(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, LoadedObjectInfoHelper(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
unsigned EndIdx) unsigned EndIdx)
: LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} : LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {}
llvm::LoadedObjectInfo *clone() const override { std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
return new Derived(static_cast<const Derived &>(*this)); return llvm::make_unique<Derived>(static_cast<const Derived &>(*this));
} }
}; };

View File

@ -248,6 +248,13 @@ class InlineAsm : public Value {
Constraint_R, Constraint_R,
Constraint_S, Constraint_S,
Constraint_T, Constraint_T,
Constraint_Um,
Constraint_Un,
Constraint_Uq,
Constraint_Us,
Constraint_Ut,
Constraint_Uv,
Constraint_Uy,
Constraint_X, Constraint_X,
Constraint_Z, Constraint_Z,
Constraint_ZC, Constraint_ZC,

View File

@ -810,6 +810,7 @@ inline Type *checkGEPType(Type *Ty) {
/// ///
class GetElementPtrInst : public Instruction { class GetElementPtrInst : public Instruction {
Type *SourceElementType; Type *SourceElementType;
Type *ResultElementType;
GetElementPtrInst(const GetElementPtrInst &GEPI); GetElementPtrInst(const GetElementPtrInst &GEPI);
void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr); void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr);
@ -903,9 +904,12 @@ class GetElementPtrInst : public Instruction {
Type *getSourceElementType() const { return SourceElementType; } Type *getSourceElementType() const { return SourceElementType; }
void setSourceElementType(Type *Ty) { SourceElementType = Ty; } void setSourceElementType(Type *Ty) { SourceElementType = Ty; }
void setResultElementType(Type *Ty) { ResultElementType = Ty; }
Type *getResultElementType() const { Type *getResultElementType() const {
return cast<PointerType>(getType()->getScalarType())->getElementType(); assert(ResultElementType ==
cast<PointerType>(getType()->getScalarType())->getElementType());
return ResultElementType;
} }
/// \brief Returns the address space of this instruction's pointer type. /// \brief Returns the address space of this instruction's pointer type.
@ -1028,7 +1032,10 @@ GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr,
: Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr, : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - Values, OperandTraits<GetElementPtrInst>::op_end(this) - Values,
Values, InsertBefore), Values, InsertBefore),
SourceElementType(PointeeType) { SourceElementType(PointeeType),
ResultElementType(getIndexedType(PointeeType, IdxList)) {
assert(ResultElementType ==
cast<PointerType>(getType()->getScalarType())->getElementType());
init(Ptr, IdxList, NameStr); init(Ptr, IdxList, NameStr);
} }
GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr,
@ -1038,7 +1045,10 @@ GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr,
: Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr, : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - Values, OperandTraits<GetElementPtrInst>::op_end(this) - Values,
Values, InsertAtEnd), Values, InsertAtEnd),
SourceElementType(PointeeType) { SourceElementType(PointeeType),
ResultElementType(getIndexedType(PointeeType, IdxList)) {
assert(ResultElementType ==
cast<PointerType>(getType()->getScalarType())->getElementType());
init(Ptr, IdxList, NameStr); init(Ptr, IdxList, NameStr);
} }

View File

@ -537,7 +537,8 @@ def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty],
def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty], def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty],
[llvm_i64_ty, llvm_i32_ty, [llvm_i64_ty, llvm_i32_ty,
llvm_anyptr_ty, llvm_i32_ty, llvm_anyptr_ty, llvm_i32_ty,
llvm_i32_ty, llvm_vararg_ty]>; llvm_i32_ty, llvm_vararg_ty],
[Throws]>;
def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>; def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>;
def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty], def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty],

View File

@ -3372,10 +3372,40 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty],
[IntrNoMem]>; [IntrNoMem]>;
def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512_mask">, def int_x86_avx512_mask_sqrt_pd_128 : GCCBuiltin<"__builtin_ia32_sqrtpd128_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_sqrt_pd_256 : GCCBuiltin<"__builtin_ia32_sqrtpd256_mask">,
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512_mask">, def int_x86_avx512_mask_sqrt_ps_128 : GCCBuiltin<"__builtin_ia32_sqrtps128_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_sqrt_ps_256 : GCCBuiltin<"__builtin_ia32_sqrtps256_mask">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_getexp_pd_128 : GCCBuiltin<"__builtin_ia32_getexppd128_mask">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_getexp_pd_256 : GCCBuiltin<"__builtin_ia32_getexppd256_mask">,
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_getexp_pd_512 : GCCBuiltin<"__builtin_ia32_getexppd512_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_mask_getexp_ps_128 : GCCBuiltin<"__builtin_ia32_getexpps128_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_getexp_ps_256 : GCCBuiltin<"__builtin_ia32_getexpps256_mask">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_getexp_ps_512 : GCCBuiltin<"__builtin_ia32_getexpps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;

View File

@ -153,7 +153,7 @@ class MDBuilder {
/// \brief Return metadata for a TBAA tag node with the given /// \brief Return metadata for a TBAA tag node with the given
/// base type, access type and offset relative to the base type. /// base type, access type and offset relative to the base type.
MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType,
uint64_t Offset); uint64_t Offset, bool IsConstant = false);
}; };
} // end namespace llvm } // end namespace llvm

View File

@ -69,9 +69,8 @@ class Value {
Type *VTy; Type *VTy;
Use *UseList; Use *UseList;
friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD. friend class ValueAsMetadata; // Allow access to IsUsedByMD.
friend class ValueHandleBase; friend class ValueHandleBase;
PointerIntPair<ValueName *, 1> NameAndIsUsedByMD;
const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast)
unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this?
@ -101,7 +100,10 @@ class Value {
/// This is stored here to save space in User on 64-bit hosts. Since most /// This is stored here to save space in User on 64-bit hosts. Since most
/// instances of Value have operands, 32-bit hosts aren't significantly /// instances of Value have operands, 32-bit hosts aren't significantly
/// affected. /// affected.
unsigned NumOperands; unsigned NumOperands : 30;
bool IsUsedByMD : 1;
bool HasName : 1;
private: private:
template <typename UseT> // UseT == 'Use' or 'const Use' template <typename UseT> // UseT == 'Use' or 'const Use'
@ -210,9 +212,9 @@ class Value {
LLVMContext &getContext() const; LLVMContext &getContext() const;
// \brief All values can potentially be named. // \brief All values can potentially be named.
bool hasName() const { return getValueName() != nullptr; } bool hasName() const { return HasName; }
ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); } ValueName *getValueName() const;
void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); } void setValueName(ValueName *VN);
private: private:
void destroyValueName(); void destroyValueName();
@ -394,7 +396,7 @@ class Value {
bool hasValueHandle() const { return HasValueHandle; } bool hasValueHandle() const { return HasValueHandle; }
/// \brief Return true if there is metadata referencing this value. /// \brief Return true if there is metadata referencing this value.
bool isUsedByMetadata() const { return NameAndIsUsedByMD.getInt(); } bool isUsedByMetadata() const { return IsUsedByMD; }
/// \brief Strip off pointer casts, all-zero GEPs, and aliases. /// \brief Strip off pointer casts, all-zero GEPs, and aliases.
/// ///

View File

@ -289,6 +289,7 @@ void initializeLoopVectorizePass(PassRegistry&);
void initializeSLPVectorizerPass(PassRegistry&); void initializeSLPVectorizerPass(PassRegistry&);
void initializeBBVectorizePass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&);
void initializeMachineFunctionPrinterPassPass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&);
void initializeMIRPrintingPassPass(PassRegistry&);
void initializeStackMapLivenessPass(PassRegistry&); void initializeStackMapLivenessPass(PassRegistry&);
void initializeMachineCombinerPass(PassRegistry &); void initializeMachineCombinerPass(PassRegistry &);
void initializeLoadCombinePass(PassRegistry&); void initializeLoadCombinePass(PassRegistry&);

View File

@ -82,7 +82,7 @@ struct LTOCodeGenerator {
void setShouldInternalize(bool Value) { ShouldInternalize = Value; } void setShouldInternalize(bool Value) { ShouldInternalize = Value; }
void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; } void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; }
void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; } void addMustPreserveSymbol(StringRef sym) { MustPreserveSymbols[sym] = 1; }
// To pass options to the driver and optimization passes. These options are // To pass options to the driver and optimization passes. These options are
// not necessarily for debugging purpose (The function name is misleading). // not necessarily for debugging purpose (The function name is misleading).
@ -117,11 +117,10 @@ struct LTOCodeGenerator {
// (linker), it brings the object to a buffer, and return the buffer to the // (linker), it brings the object to a buffer, and return the buffer to the
// caller. This function should delete intermediate object file once its content // caller. This function should delete intermediate object file once its content
// is brought to memory. Return NULL if the compilation was not successful. // is brought to memory. Return NULL if the compilation was not successful.
const void *compile(size_t *length, std::unique_ptr<MemoryBuffer> compile(bool disableInline,
bool disableInline, bool disableGVNLoadPRE,
bool disableGVNLoadPRE, bool disableVectorization,
bool disableVectorization, std::string &errMsg);
std::string &errMsg);
// Optimizes the merged module. Returns true on success. // Optimizes the merged module. Returns true on success.
bool optimize(bool disableInline, bool optimize(bool disableInline,
@ -132,7 +131,7 @@ struct LTOCodeGenerator {
// Compiles the merged optimized module into a single object file. It brings // Compiles the merged optimized module into a single object file. It brings
// the object to a buffer, and returns the buffer to the caller. Return NULL // the object to a buffer, and returns the buffer to the caller. Return NULL
// if the compilation was not successful. // if the compilation was not successful.
const void *compileOptimized(size_t *length, std::string &errMsg); std::unique_ptr<MemoryBuffer> compileOptimized(std::string &errMsg);
void setDiagnosticHandler(lto_diagnostic_handler_t, void *); void setDiagnosticHandler(lto_diagnostic_handler_t, void *);
@ -166,7 +165,6 @@ struct LTOCodeGenerator {
lto_codegen_model CodeModel = LTO_CODEGEN_PIC_MODEL_DEFAULT; lto_codegen_model CodeModel = LTO_CODEGEN_PIC_MODEL_DEFAULT;
StringSet MustPreserveSymbols; StringSet MustPreserveSymbols;
StringSet AsmUndefinedRefs; StringSet AsmUndefinedRefs;
std::unique_ptr<MemoryBuffer> NativeObjectFile;
std::vector<char *> CodegenOptions; std::vector<char *> CodegenOptions;
std::string MCpu; std::string MCpu;
std::string MAttr; std::string MAttr;

View File

@ -97,6 +97,12 @@ class MCAsmBackend {
/// Target specific predicate for whether a given fixup requires the /// Target specific predicate for whether a given fixup requires the
/// associated instruction to be relaxed. /// associated instruction to be relaxed.
virtual bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
uint64_t Value,
const MCRelaxableFragment *DF,
const MCAsmLayout &Layout) const;
/// Simple predicate for targets where !Resolved implies requiring relaxation
virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
const MCRelaxableFragment *DF, const MCRelaxableFragment *DF,
const MCAsmLayout &Layout) const = 0; const MCAsmLayout &Layout) const = 0;

View File

@ -155,6 +155,10 @@ class MCAsmInfo {
/// Defaults to false. /// Defaults to false.
bool AllowAtInName; bool AllowAtInName;
/// If this is true, symbol names with invalid characters will be printed in
/// quotes.
bool SupportsQuotedNames;
/// This is true if data region markers should be printed as /// This is true if data region markers should be printed as
/// ".data_region/.end_data_region" directives. If false, use "$d/$a" labels /// ".data_region/.end_data_region" directives. If false, use "$d/$a" labels
/// instead. /// instead.
@ -406,6 +410,10 @@ class MCAsmInfo {
unsigned Encoding, unsigned Encoding,
MCStreamer &Streamer) const; MCStreamer &Streamer) const;
/// Return true if the identifier \p Name does not need quotes to be
/// syntactically correct.
virtual bool isValidUnquotedName(StringRef Name) const;
bool usesSunStyleELFSectionSwitchSyntax() const { bool usesSunStyleELFSectionSwitchSyntax() const {
return SunStyleELFSectionSwitchSyntax; return SunStyleELFSectionSwitchSyntax;
} }
@ -456,6 +464,7 @@ class MCAsmInfo {
const char *getCode64Directive() const { return Code64Directive; } const char *getCode64Directive() const { return Code64Directive; }
unsigned getAssemblerDialect() const { return AssemblerDialect; } unsigned getAssemblerDialect() const { return AssemblerDialect; }
bool doesAllowAtInName() const { return AllowAtInName; } bool doesAllowAtInName() const { return AllowAtInName; }
bool supportsNameQuoting() const { return SupportsQuotedNames; }
bool doesSupportDataRegionDirectives() const { bool doesSupportDataRegionDirectives() const {
return UseDataRegionDirectives; return UseDataRegionDirectives;
} }

View File

@ -18,7 +18,6 @@ class MCAssembler;
class MCFragment; class MCFragment;
class MCSection; class MCSection;
class MCSymbol; class MCSymbol;
class MCSymbolData;
/// Encapsulates the layout of an assembly file at a particular point in time. /// Encapsulates the layout of an assembly file at a particular point in time.
/// ///

View File

@ -12,7 +12,6 @@
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist.h"
@ -24,7 +23,6 @@
#include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include <algorithm> #include <algorithm>
@ -60,7 +58,8 @@ class MCFragment : public ilist_node<MCFragment> {
FT_Org, FT_Org,
FT_Dwarf, FT_Dwarf,
FT_DwarfFrame, FT_DwarfFrame,
FT_LEB FT_LEB,
FT_SafeSEH
}; };
private: private:
@ -531,6 +530,28 @@ class MCDwarfCallFrameFragment : public MCFragment {
} }
}; };
class MCSafeSEHFragment : public MCFragment {
virtual void anchor();
const MCSymbol *Sym;
public:
MCSafeSEHFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
: MCFragment(FT_SafeSEH, Sec), Sym(Sym) {}
/// \name Accessors
/// @{
const MCSymbol *getSymbol() { return Sym; }
const MCSymbol *getSymbol() const { return Sym; }
/// @}
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_SafeSEH;
}
};
// FIXME: This really doesn't belong here. See comments below. // FIXME: This really doesn't belong here. See comments below.
struct IndirectSymbolData { struct IndirectSymbolData {
MCSymbol *Symbol; MCSymbol *Symbol;
@ -551,7 +572,7 @@ class MCAssembler {
friend class MCAsmLayout; friend class MCAsmLayout;
public: public:
typedef SetVector<MCSection *> SectionListType; typedef std::vector<MCSection *> SectionListType;
typedef std::vector<const MCSymbol *> SymbolDataListType; typedef std::vector<const MCSymbol *> SymbolDataListType;
typedef pointee_iterator<SectionListType::const_iterator> const_iterator; typedef pointee_iterator<SectionListType::const_iterator> const_iterator;
@ -564,9 +585,6 @@ class MCAssembler {
typedef iterator_range<symbol_iterator> symbol_range; typedef iterator_range<symbol_iterator> symbol_range;
typedef iterator_range<const_symbol_iterator> const_symbol_range; typedef iterator_range<const_symbol_iterator> const_symbol_range;
typedef std::vector<std::string> FileNameVectorType;
typedef FileNameVectorType::const_iterator const_file_name_iterator;
typedef std::vector<IndirectSymbolData>::const_iterator typedef std::vector<IndirectSymbolData>::const_iterator
const_indirect_symbol_iterator; const_indirect_symbol_iterator;
typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator; typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
@ -613,7 +631,7 @@ class MCAssembler {
std::vector<std::vector<std::string>> LinkerOptions; std::vector<std::vector<std::string>> LinkerOptions;
/// List of declared file names /// List of declared file names
FileNameVectorType FileNames; std::vector<std::string> FileNames;
/// The set of function symbols for which a .thumb_func directive has /// The set of function symbols for which a .thumb_func directive has
/// been seen. /// been seen.
@ -883,39 +901,21 @@ class MCAssembler {
/// \name Backend Data Access /// \name Backend Data Access
/// @{ /// @{
bool registerSection(MCSection &Section) { return Sections.insert(&Section); } bool registerSection(MCSection &Section) {
if (Section.isRegistered())
bool hasSymbolData(const MCSymbol &Symbol) const { return Symbol.hasData(); } return false;
Sections.push_back(&Section);
MCSymbolData &getSymbolData(const MCSymbol &Symbol) { Section.setIsRegistered(true);
return const_cast<MCSymbolData &>( return true;
static_cast<const MCAssembler &>(*this).getSymbolData(Symbol));
} }
const MCSymbolData &getSymbolData(const MCSymbol &Symbol) const { void registerSymbol(const MCSymbol &Symbol, bool *Created = nullptr);
return Symbol.getData();
}
MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol, ArrayRef<std::string> getFileNames() { return FileNames; }
bool *Created = nullptr) {
if (Created)
*Created = !hasSymbolData(Symbol);
if (!hasSymbolData(Symbol)) {
Symbol.initializeData();
Symbols.push_back(&Symbol);
}
return Symbol.getData();
}
const_file_name_iterator file_names_begin() const {
return FileNames.begin();
}
const_file_name_iterator file_names_end() const { return FileNames.end(); }
void addFileName(StringRef FileName) { void addFileName(StringRef FileName) {
if (std::find(file_names_begin(), file_names_end(), FileName) == if (std::find(FileNames.begin(), FileNames.end(), FileName) ==
file_names_end()) FileNames.end())
FileNames.push_back(FileName); FileNames.push_back(FileName);
} }

View File

@ -30,6 +30,7 @@ namespace llvm {
class MCExpr; class MCExpr;
class MCSection; class MCSection;
class MCSymbol; class MCSymbol;
class MCSymbolELF;
class MCLabel; class MCLabel;
struct MCDwarfFile; struct MCDwarfFile;
class MCDwarfLoc; class MCDwarfLoc;
@ -75,7 +76,7 @@ namespace llvm {
/// ELF sections can have a corresponding symbol. This maps one to the /// ELF sections can have a corresponding symbol. This maps one to the
/// other. /// other.
DenseMap<const MCSectionELF *, MCSymbol *> SectionSymbols; DenseMap<const MCSectionELF *, MCSymbolELF *> SectionSymbols;
/// A mapping from a local label number and an instance count to a symbol. /// A mapping from a local label number and an instance count to a symbol.
/// For example, in the assembly /// For example, in the assembly
@ -205,7 +206,10 @@ namespace llvm {
/// Do automatic reset in destructor /// Do automatic reset in destructor
bool AutoReset; bool AutoReset;
MCSymbol *CreateSymbol(StringRef Name, bool AlwaysAddSuffix); MCSymbol *createSymbolImpl(const StringMapEntry<bool> *Name,
bool IsTemporary);
MCSymbol *createSymbol(StringRef Name, bool AlwaysAddSuffix,
bool IsTemporary);
MCSymbol *getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal, MCSymbol *getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal,
unsigned Instance); unsigned Instance);
@ -263,7 +267,7 @@ namespace llvm {
/// \param Name - The symbol name, which must be unique across all symbols. /// \param Name - The symbol name, which must be unique across all symbols.
MCSymbol *getOrCreateSymbol(const Twine &Name); MCSymbol *getOrCreateSymbol(const Twine &Name);
MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); MCSymbolELF *getOrCreateSectionSymbol(const MCSectionELF &Section);
/// Gets a symbol that will be defined to the final stack offset of a local /// Gets a symbol that will be defined to the final stack offset of a local
/// variable after codegen. /// variable after codegen.
@ -340,18 +344,18 @@ namespace llvm {
MCSectionELF *getELFSection(StringRef Section, unsigned Type, MCSectionELF *getELFSection(StringRef Section, unsigned Type,
unsigned Flags, unsigned EntrySize, unsigned Flags, unsigned EntrySize,
const MCSymbol *Group, unsigned UniqueID, const MCSymbolELF *Group, unsigned UniqueID,
const char *BeginSymName, const char *BeginSymName,
const MCSectionELF *Associated); const MCSectionELF *Associated);
MCSectionELF *createELFRelSection(StringRef Name, unsigned Type, MCSectionELF *createELFRelSection(StringRef Name, unsigned Type,
unsigned Flags, unsigned EntrySize, unsigned Flags, unsigned EntrySize,
const MCSymbol *Group, const MCSymbolELF *Group,
const MCSectionELF *Associated); const MCSectionELF *Associated);
void renameELFSection(MCSectionELF *Section, StringRef Name); void renameELFSection(MCSectionELF *Section, StringRef Name);
MCSectionELF *createELFGroupSection(const MCSymbol *Group); MCSectionELF *createELFGroupSection(const MCSymbolELF *Group);
MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
SectionKind Kind, StringRef COMDATSymName, SectionKind Kind, StringRef COMDATSymName,

View File

@ -1,35 +0,0 @@
//===- lib/MC/MCELF.h - ELF MC --------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains some support functions used by the ELF Streamer and
// ObjectWriter.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_MC_MCELF_H
#define LLVM_MC_MCELF_H
namespace llvm {
class MCSymbolData;
class MCELF {
public:
static void SetBinding(MCSymbolData &SD, unsigned Binding);
static unsigned GetBinding(const MCSymbolData &SD);
static void SetType(MCSymbolData &SD, unsigned Type);
static unsigned GetType(const MCSymbolData &SD);
static void SetVisibility(MCSymbolData &SD, unsigned Visibility);
static unsigned GetVisibility(const MCSymbolData &SD);
static void setOther(MCSymbolData &SD, unsigned Other);
static unsigned getOther(const MCSymbolData &SD);
};
}
#endif

View File

@ -21,17 +21,17 @@ class MCFixup;
class MCFragment; class MCFragment;
class MCObjectWriter; class MCObjectWriter;
class MCSymbol; class MCSymbol;
class MCSymbolData; class MCSymbolELF;
class MCValue; class MCValue;
class raw_pwrite_stream; class raw_pwrite_stream;
struct ELFRelocationEntry { struct ELFRelocationEntry {
uint64_t Offset; // Where is the relocation. uint64_t Offset; // Where is the relocation.
const MCSymbol *Symbol; // The symbol to relocate with. const MCSymbolELF *Symbol; // The symbol to relocate with.
unsigned Type; // The type of the relocation. unsigned Type; // The type of the relocation.
uint64_t Addend; // The addend to use. uint64_t Addend; // The addend to use.
ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type, ELFRelocationEntry(uint64_t Offset, const MCSymbolELF *Symbol, unsigned Type,
uint64_t Addend) uint64_t Addend)
: Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {} : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {}
}; };
@ -69,7 +69,7 @@ class MCELFObjectTargetWriter {
virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
bool IsPCRel) const = 0; bool IsPCRel) const = 0;
virtual bool needsRelocateWithSymbol(const MCSymbolData &SD, virtual bool needsRelocateWithSymbol(const MCSymbol &Sym,
unsigned Type) const; unsigned Type) const;
virtual void sortRelocs(const MCAssembler &Asm, virtual void sortRelocs(const MCAssembler &Asm,

View File

@ -23,8 +23,6 @@ class MCAssembler;
class MCCodeEmitter; class MCCodeEmitter;
class MCExpr; class MCExpr;
class MCInst; class MCInst;
class MCSymbol;
class MCSymbolData;
class raw_ostream; class raw_ostream;
class MCELFStreamer : public MCObjectStreamer { class MCELFStreamer : public MCObjectStreamer {
@ -39,7 +37,6 @@ class MCELFStreamer : public MCObjectStreamer {
void reset() override { void reset() override {
SeenIdent = false; SeenIdent = false;
LocalCommons.clear(); LocalCommons.clear();
BindingExplicitlySet.clear();
BundleGroups.clear(); BundleGroups.clear();
MCObjectStreamer::reset(); MCObjectStreamer::reset();
} }
@ -62,7 +59,7 @@ class MCELFStreamer : public MCObjectStreamer {
void EmitCOFFSymbolType(int Type) override; void EmitCOFFSymbolType(int Type) override;
void EndCOFFSymbolDef() override; void EndCOFFSymbolDef() override;
void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) override;
void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override; unsigned ByteAlignment) override;
@ -108,8 +105,6 @@ class MCELFStreamer : public MCObjectStreamer {
std::vector<LocalCommon> LocalCommons; std::vector<LocalCommon> LocalCommons;
SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet;
/// BundleGroups - The stack of fragments holding the bundle-locked /// BundleGroups - The stack of fragments holding the bundle-locked
/// instructions. /// instructions.
llvm::SmallVector<MCDataFragment *, 4> BundleGroups; llvm::SmallVector<MCDataFragment *, 4> BundleGroups;

View File

@ -1,56 +0,0 @@
//===- MCELFSymbolFlags.h - ELF Symbol Flags ----------------*- 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 SymbolFlags used for the ELF target.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_MC_MCELFSYMBOLFLAGS_H
#define LLVM_MC_MCELFSYMBOLFLAGS_H
#include "llvm/Support/ELF.h"
// Because all the symbol flags need to be stored in the MCSymbolData
// 'flags' variable we need to provide shift constants per flag type.
namespace llvm {
enum {
ELF_STT_Shift = 0, // Shift value for STT_* flags.
ELF_STB_Shift = 4, // Shift value for STB_* flags.
ELF_STV_Shift = 8, // Shift value for STV_* flags.
ELF_STO_Shift = 10 // Shift value for STO_* flags.
};
enum ELFSymbolFlags {
ELF_STB_Local = (ELF::STB_LOCAL << ELF_STB_Shift),
ELF_STB_Global = (ELF::STB_GLOBAL << ELF_STB_Shift),
ELF_STB_Weak = (ELF::STB_WEAK << ELF_STB_Shift),
ELF_STB_Loproc = (ELF::STB_LOPROC << ELF_STB_Shift),
ELF_STB_Hiproc = (ELF::STB_HIPROC << ELF_STB_Shift),
ELF_STT_Notype = (ELF::STT_NOTYPE << ELF_STT_Shift),
ELF_STT_Object = (ELF::STT_OBJECT << ELF_STT_Shift),
ELF_STT_Func = (ELF::STT_FUNC << ELF_STT_Shift),
ELF_STT_Section = (ELF::STT_SECTION << ELF_STT_Shift),
ELF_STT_File = (ELF::STT_FILE << ELF_STT_Shift),
ELF_STT_Common = (ELF::STT_COMMON << ELF_STT_Shift),
ELF_STT_Tls = (ELF::STT_TLS << ELF_STT_Shift),
ELF_STT_GnuIFunc = (ELF::STT_GNU_IFUNC << ELF_STT_Shift),
ELF_STT_Loproc = (ELF::STT_LOPROC << ELF_STT_Shift),
ELF_STT_Hiproc = (ELF::STT_HIPROC << ELF_STT_Shift),
ELF_STV_Default = (ELF::STV_DEFAULT << ELF_STV_Shift),
ELF_STV_Internal = (ELF::STV_INTERNAL << ELF_STV_Shift),
ELF_STV_Hidden = (ELF::STV_HIDDEN << ELF_STV_Shift),
ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift)
};
} // end namespace llvm
#endif

View File

@ -46,7 +46,7 @@ class MCExpr {
MCExpr(const MCExpr&) = delete; MCExpr(const MCExpr&) = delete;
void operator=(const MCExpr&) = delete; void operator=(const MCExpr&) = delete;
bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout, const MCAsmLayout *Layout,
const SectionAddrMap *Addrs) const; const SectionAddrMap *Addrs) const;
@ -57,7 +57,7 @@ class MCExpr {
protected: protected:
explicit MCExpr(ExprKind Kind) : Kind(Kind) {} explicit MCExpr(ExprKind Kind) : Kind(Kind) {}
bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout, const MCAsmLayout *Layout,
const MCFixup *Fixup, const MCFixup *Fixup,
const SectionAddrMap *Addrs, bool InSet) const; const SectionAddrMap *Addrs, bool InSet) const;
@ -72,7 +72,7 @@ class MCExpr {
/// \name Utility Methods /// \name Utility Methods
/// @{ /// @{
void print(raw_ostream &OS) const; void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
void dump() const; void dump() const;
/// @} /// @}
@ -86,11 +86,11 @@ class MCExpr {
/// values. If not given, then only non-symbolic expressions will be /// values. If not given, then only non-symbolic expressions will be
/// evaluated. /// evaluated.
/// \return - True on success. /// \return - True on success.
bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout,
const SectionAddrMap &Addrs) const; const SectionAddrMap &Addrs) const;
bool EvaluateAsAbsolute(int64_t &Res) const; bool evaluateAsAbsolute(int64_t &Res) const;
bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const;
bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
@ -101,13 +101,13 @@ class MCExpr {
/// \param Layout - The assembler layout object to use for evaluating values. /// \param Layout - The assembler layout object to use for evaluating values.
/// \param Fixup - The Fixup object if available. /// \param Fixup - The Fixup object if available.
/// \return - True on success. /// \return - True on success.
bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout,
const MCFixup *Fixup) const; const MCFixup *Fixup) const;
/// \brief Try to evaluate the expression to the form (a - b + constant) where /// \brief Try to evaluate the expression to the form (a - b + constant) where
/// neither a nor b are variables. /// neither a nor b are variables.
/// ///
/// This is a more aggressive variant of EvaluateAsRelocatable. The intended /// This is a more aggressive variant of evaluateAsRelocatable. The intended
/// use is for when relocations are not available, like the .size directive. /// use is for when relocations are not available, like the .size directive.
bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const; bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const;
@ -115,13 +115,13 @@ class MCExpr {
/// currently defined as the absolute section for constants, or /// currently defined as the absolute section for constants, or
/// otherwise the section associated with the first defined symbol in the /// otherwise the section associated with the first defined symbol in the
/// expression. /// expression.
MCSection *FindAssociatedSection() const; MCSection *findAssociatedSection() const;
/// @} /// @}
}; };
inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) {
E.print(OS); E.print(OS, nullptr);
return OS; return OS;
} }
@ -136,7 +136,7 @@ class MCConstantExpr : public MCExpr {
/// \name Construction /// \name Construction
/// @{ /// @{
static const MCConstantExpr *Create(int64_t Value, MCContext &Ctx); static const MCConstantExpr *create(int64_t Value, MCContext &Ctx);
/// @} /// @}
/// \name Accessors /// \name Accessors
@ -312,13 +312,13 @@ class MCSymbolRefExpr : public MCExpr {
/// \name Construction /// \name Construction
/// @{ /// @{
static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, MCContext &Ctx) { static const MCSymbolRefExpr *create(const MCSymbol *Symbol, MCContext &Ctx) {
return MCSymbolRefExpr::Create(Symbol, VK_None, Ctx); return MCSymbolRefExpr::create(Symbol, VK_None, Ctx);
} }
static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, VariantKind Kind, static const MCSymbolRefExpr *create(const MCSymbol *Symbol, VariantKind Kind,
MCContext &Ctx); MCContext &Ctx);
static const MCSymbolRefExpr *Create(StringRef Name, VariantKind Kind, static const MCSymbolRefExpr *create(StringRef Name, VariantKind Kind,
MCContext &Ctx); MCContext &Ctx);
/// @} /// @}
@ -369,19 +369,19 @@ class MCUnaryExpr : public MCExpr {
/// \name Construction /// \name Construction
/// @{ /// @{
static const MCUnaryExpr *Create(Opcode Op, const MCExpr *Expr, static const MCUnaryExpr *create(Opcode Op, const MCExpr *Expr,
MCContext &Ctx); MCContext &Ctx);
static const MCUnaryExpr *CreateLNot(const MCExpr *Expr, MCContext &Ctx) { static const MCUnaryExpr *createLNot(const MCExpr *Expr, MCContext &Ctx) {
return Create(LNot, Expr, Ctx); return create(LNot, Expr, Ctx);
} }
static const MCUnaryExpr *CreateMinus(const MCExpr *Expr, MCContext &Ctx) { static const MCUnaryExpr *createMinus(const MCExpr *Expr, MCContext &Ctx) {
return Create(Minus, Expr, Ctx); return create(Minus, Expr, Ctx);
} }
static const MCUnaryExpr *CreateNot(const MCExpr *Expr, MCContext &Ctx) { static const MCUnaryExpr *createNot(const MCExpr *Expr, MCContext &Ctx) {
return Create(Not, Expr, Ctx); return create(Not, Expr, Ctx);
} }
static const MCUnaryExpr *CreatePlus(const MCExpr *Expr, MCContext &Ctx) { static const MCUnaryExpr *createPlus(const MCExpr *Expr, MCContext &Ctx) {
return Create(Plus, Expr, Ctx); return create(Plus, Expr, Ctx);
} }
/// @} /// @}
@ -441,83 +441,83 @@ class MCBinaryExpr : public MCExpr {
/// \name Construction /// \name Construction
/// @{ /// @{
static const MCBinaryExpr *Create(Opcode Op, const MCExpr *LHS, static const MCBinaryExpr *create(Opcode Op, const MCExpr *LHS,
const MCExpr *RHS, MCContext &Ctx); const MCExpr *RHS, MCContext &Ctx);
static const MCBinaryExpr *CreateAdd(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createAdd(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(Add, LHS, RHS, Ctx); return create(Add, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateAnd(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createAnd(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(And, LHS, RHS, Ctx); return create(And, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateDiv(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createDiv(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(Div, LHS, RHS, Ctx); return create(Div, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateEQ(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createEQ(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(EQ, LHS, RHS, Ctx); return create(EQ, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateGT(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createGT(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(GT, LHS, RHS, Ctx); return create(GT, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateGTE(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createGTE(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(GTE, LHS, RHS, Ctx); return create(GTE, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateLAnd(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createLAnd(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(LAnd, LHS, RHS, Ctx); return create(LAnd, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateLOr(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createLOr(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(LOr, LHS, RHS, Ctx); return create(LOr, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateLT(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createLT(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(LT, LHS, RHS, Ctx); return create(LT, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateLTE(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createLTE(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(LTE, LHS, RHS, Ctx); return create(LTE, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateMod(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createMod(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(Mod, LHS, RHS, Ctx); return create(Mod, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateMul(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createMul(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(Mul, LHS, RHS, Ctx); return create(Mul, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateNE(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createNE(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(NE, LHS, RHS, Ctx); return create(NE, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateOr(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createOr(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(Or, LHS, RHS, Ctx); return create(Or, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateShl(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createShl(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(Shl, LHS, RHS, Ctx); return create(Shl, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateAShr(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createAShr(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(AShr, LHS, RHS, Ctx); return create(AShr, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateLShr(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createLShr(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(LShr, LHS, RHS, Ctx); return create(LShr, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateSub(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createSub(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(Sub, LHS, RHS, Ctx); return create(Sub, LHS, RHS, Ctx);
} }
static const MCBinaryExpr *CreateXor(const MCExpr *LHS, const MCExpr *RHS, static const MCBinaryExpr *createXor(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) { MCContext &Ctx) {
return Create(Xor, LHS, RHS, Ctx); return create(Xor, LHS, RHS, Ctx);
} }
/// @} /// @}
@ -551,13 +551,12 @@ class MCTargetExpr : public MCExpr {
MCTargetExpr() : MCExpr(Target) {} MCTargetExpr() : MCExpr(Target) {}
virtual ~MCTargetExpr() {} virtual ~MCTargetExpr() {}
public: public:
virtual void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const = 0;
virtual void PrintImpl(raw_ostream &OS) const = 0; virtual bool evaluateAsRelocatableImpl(MCValue &Res,
virtual bool EvaluateAsRelocatableImpl(MCValue &Res,
const MCAsmLayout *Layout, const MCAsmLayout *Layout,
const MCFixup *Fixup) const = 0; const MCFixup *Fixup) const = 0;
virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; virtual void visitUsedExpr(MCStreamer& Streamer) const = 0;
virtual MCSection *FindAssociatedSection() const = 0; virtual MCSection *findAssociatedSection() const = 0;
virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0; virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0;

View File

@ -32,12 +32,12 @@ class MCInst;
/// This is a simple discriminated union. /// This is a simple discriminated union.
class MCOperand { class MCOperand {
enum MachineOperandType : unsigned char { enum MachineOperandType : unsigned char {
kInvalid, ///< Uninitialized. kInvalid, ///< Uninitialized.
kRegister, ///< Register operand. kRegister, ///< Register operand.
kImmediate, ///< Immediate operand. kImmediate, ///< Immediate operand.
kFPImmediate, ///< Floating-point immediate operand. kFPImmediate, ///< Floating-point immediate operand.
kExpr, ///< Relocatable immediate operand. kExpr, ///< Relocatable immediate operand.
kInst ///< Sub-instruction operand. kInst ///< Sub-instruction operand.
}; };
MachineOperandType Kind; MachineOperandType Kind;
@ -48,8 +48,8 @@ class MCOperand {
const MCExpr *ExprVal; const MCExpr *ExprVal;
const MCInst *InstVal; const MCInst *InstVal;
}; };
public:
public:
MCOperand() : Kind(kInvalid), FPImmVal(0.0) {} MCOperand() : Kind(kInvalid), FPImmVal(0.0) {}
bool isValid() const { return Kind != kInvalid; } bool isValid() const { return Kind != kInvalid; }
@ -151,6 +151,7 @@ class MCInst {
unsigned Opcode; unsigned Opcode;
SMLoc Loc; SMLoc Loc;
SmallVector<MCOperand, 8> Operands; SmallVector<MCOperand, 8> Operands;
public: public:
MCInst() : Opcode(0) {} MCInst() : Opcode(0) {}
@ -164,18 +165,16 @@ class MCInst {
MCOperand &getOperand(unsigned i) { return Operands[i]; } MCOperand &getOperand(unsigned i) { return Operands[i]; }
unsigned getNumOperands() const { return Operands.size(); } unsigned getNumOperands() const { return Operands.size(); }
void addOperand(const MCOperand &Op) { void addOperand(const MCOperand &Op) { Operands.push_back(Op); }
Operands.push_back(Op);
}
void clear() { Operands.clear(); }
size_t size() const { return Operands.size(); }
typedef SmallVectorImpl<MCOperand>::iterator iterator; typedef SmallVectorImpl<MCOperand>::iterator iterator;
typedef SmallVectorImpl<MCOperand>::const_iterator const_iterator; typedef SmallVectorImpl<MCOperand>::const_iterator const_iterator;
void clear() { Operands.clear(); }
void erase(iterator I) { Operands.erase(I); }
size_t size() const { return Operands.size(); }
iterator begin() { return Operands.begin(); } iterator begin() { return Operands.begin(); }
const_iterator begin() const { return Operands.begin(); } const_iterator begin() const { return Operands.begin(); }
iterator end() { return Operands.end(); } iterator end() { return Operands.end(); }
const_iterator end() const { return Operands.end(); } const_iterator end() const { return Operands.end(); }
iterator insert(iterator I, const MCOperand &Op) { iterator insert(iterator I, const MCOperand &Op) {
return Operands.insert(I, Op); return Operands.insert(I, Op);

View File

@ -10,6 +10,7 @@
#ifndef LLVM_MC_MCINSTPRINTER_H #ifndef LLVM_MC_MCINSTPRINTER_H
#define LLVM_MC_MCINSTPRINTER_H #define LLVM_MC_MCINSTPRINTER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
@ -22,11 +23,14 @@ class MCRegisterInfo;
class MCSubtargetInfo; class MCSubtargetInfo;
class StringRef; class StringRef;
/// Convert `Bytes' to a hex string and output to `OS'
void dumpBytes(ArrayRef<uint8_t> Bytes, raw_ostream &OS);
namespace HexStyle { namespace HexStyle {
enum Style { enum Style {
C, ///< 0xff C, ///< 0xff
Asm ///< 0ffh Asm ///< 0ffh
}; };
} }
/// \brief This is an instance of a target assembly language printer that /// \brief This is an instance of a target assembly language printer that
@ -52,12 +56,12 @@ class MCInstPrinter {
/// Utility function for printing annotations. /// Utility function for printing annotations.
void printAnnotation(raw_ostream &OS, StringRef Annot); void printAnnotation(raw_ostream &OS, StringRef Annot);
public: public:
MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii,
const MCRegisterInfo &mri) const MCRegisterInfo &mri)
: CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri), : CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri), UseMarkup(0),
UseMarkup(0), PrintImmHex(0), PrintImmHex(0), PrintHexStyle(HexStyle::C) {}
PrintHexStyle(HexStyle::C) {}
virtual ~MCInstPrinter(); virtual ~MCInstPrinter();
@ -65,8 +69,8 @@ class MCInstPrinter {
void setCommentStream(raw_ostream &OS) { CommentStream = &OS; } void setCommentStream(raw_ostream &OS) { CommentStream = &OS; }
/// \brief Print the specified MCInst to the specified raw_ostream. /// \brief Print the specified MCInst to the specified raw_ostream.
virtual void printInst(const MCInst *MI, raw_ostream &OS, virtual void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot,
StringRef Annot, const MCSubtargetInfo &STI) = 0; const MCSubtargetInfo &STI) = 0;
/// \brief Return the name of the specified opcode enum (e.g. "MOV32ri") or /// \brief Return the name of the specified opcode enum (e.g. "MOV32ri") or
/// empty if we can't resolve it. /// empty if we can't resolve it.
@ -85,8 +89,8 @@ class MCInstPrinter {
bool getPrintImmHex() const { return PrintImmHex; } bool getPrintImmHex() const { return PrintImmHex; }
void setPrintImmHex(bool Value) { PrintImmHex = Value; } void setPrintImmHex(bool Value) { PrintImmHex = Value; }
HexStyle::Style getPrintHexStyleHex() const { return PrintHexStyle; } HexStyle::Style getPrintHexStyle() const { return PrintHexStyle; }
void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; } void setPrintHexStyle(HexStyle::Style Value) { PrintHexStyle = Value; }
/// Utility function to print immediates in decimal or hex. /// Utility function to print immediates in decimal or hex.
format_object<int64_t> formatImm(int64_t Value) const { format_object<int64_t> formatImm(int64_t Value) const {

View File

@ -125,7 +125,8 @@ enum Flag {
ExtraDefRegAllocReq, ExtraDefRegAllocReq,
RegSequence, RegSequence,
ExtractSubreg, ExtractSubreg,
InsertSubreg InsertSubreg,
Convergent
}; };
} }
@ -138,10 +139,10 @@ class MCInstrDesc {
public: public:
unsigned short Opcode; // The opcode number unsigned short Opcode; // The opcode number
unsigned short NumOperands; // Num of args (may be more if variable_ops) unsigned short NumOperands; // Num of args (may be more if variable_ops)
unsigned short NumDefs; // Num of args that are definitions unsigned char NumDefs; // Num of args that are definitions
unsigned char Size; // Number of bytes in encoding.
unsigned short SchedClass; // enum identifying instr sched class unsigned short SchedClass; // enum identifying instr sched class
unsigned short Size; // Number of bytes in encoding. uint64_t Flags; // Flags identifying machine instr class
unsigned Flags; // Flags identifying machine instr class
uint64_t TSFlags; // Target Specific Flag values uint64_t TSFlags; // Target Specific Flag values
const uint16_t *ImplicitUses; // Registers implicitly read by this instr const uint16_t *ImplicitUses; // Registers implicitly read by this instr
const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr
@ -331,6 +332,13 @@ class MCInstrDesc {
/// override accordingly. /// override accordingly.
bool isInsertSubregLike() const { return Flags & (1 << MCID::InsertSubreg); } bool isInsertSubregLike() const { return Flags & (1 << MCID::InsertSubreg); }
/// \brief Return true if this instruction is convergent.
///
/// Convergent instructions may only be moved to locations that are
/// control-equivalent to their original positions.
bool isConvergent() const { return Flags & (1 << MCID::Convergent); }
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Side Effect Analysis // Side Effect Analysis
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//

View File

@ -17,41 +17,41 @@
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
namespace llvm { namespace llvm {
class MCContext; class MCContext;
class raw_ostream; class raw_ostream;
/// \brief Instances of this class represent a label name in the MC file, /// \brief Instances of this class represent a label name in the MC file,
/// and MCLabel are created and uniqued by the MCContext class. MCLabel /// and MCLabel are created and uniqued by the MCContext class. MCLabel
/// should only be constructed for valid instances in the object file. /// should only be constructed for valid instances in the object file.
class MCLabel { class MCLabel {
// \brief The instance number of this Directional Local Label. // \brief The instance number of this Directional Local Label.
unsigned Instance; unsigned Instance;
private: // MCContext creates and uniques these. private: // MCContext creates and uniques these.
friend class MCContext; friend class MCContext;
MCLabel(unsigned instance) MCLabel(unsigned instance) : Instance(instance) {}
: Instance(instance) {}
MCLabel(const MCLabel&) = delete; MCLabel(const MCLabel &) = delete;
void operator=(const MCLabel&) = delete; void operator=(const MCLabel &) = delete;
public:
/// \brief Get the current instance of this Directional Local Label.
unsigned getInstance() const { return Instance; }
/// \brief Increment the current instance of this Directional Local Label. public:
unsigned incInstance() { return ++Instance; } /// \brief Get the current instance of this Directional Local Label.
unsigned getInstance() const { return Instance; }
/// \brief Print the value to the stream \p OS. /// \brief Increment the current instance of this Directional Local Label.
void print(raw_ostream &OS) const; unsigned incInstance() { return ++Instance; }
/// \brief Print the value to stderr. /// \brief Print the value to the stream \p OS.
void dump() const; void print(raw_ostream &OS) const;
};
inline raw_ostream &operator<<(raw_ostream &OS, const MCLabel &Label) { /// \brief Print the value to stderr.
Label.print(OS); void dump() const;
return OS; };
}
inline raw_ostream &operator<<(raw_ostream &OS, const MCLabel &Label) {
Label.print(OS);
return OS;
}
} // end namespace llvm } // end namespace llvm
#endif #endif

View File

@ -106,7 +106,7 @@ class MCLOHDirective {
/// Emit this directive in \p OutStream using the information available /// Emit this directive in \p OutStream using the information available
/// in the given \p ObjWriter and \p Layout to get the address of the /// in the given \p ObjWriter and \p Layout to get the address of the
/// arguments within the object file. /// arguments within the object file.
void Emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter, void emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter,
const MCAsmLayout &Layout) const; const MCAsmLayout &Layout) const;
public: public:
@ -123,9 +123,9 @@ class MCLOHDirective {
/// Emit this directive as: /// Emit this directive as:
/// <kind, numArgs, addr1, ..., addrN> /// <kind, numArgs, addr1, ..., addrN>
void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
raw_ostream &OutStream = ObjWriter.getStream(); raw_ostream &OutStream = ObjWriter.getStream();
Emit_impl(OutStream, ObjWriter, Layout); emit_impl(OutStream, ObjWriter, Layout);
} }
/// Get the size in bytes of this directive if emitted in \p ObjWriter with /// Get the size in bytes of this directive if emitted in \p ObjWriter with
@ -145,7 +145,7 @@ class MCLOHDirective {
}; };
raw_counting_ostream OutStream; raw_counting_ostream OutStream;
Emit_impl(OutStream, ObjWriter, Layout); emit_impl(OutStream, ObjWriter, Layout);
return OutStream.tell(); return OutStream.tell();
} }
}; };
@ -184,10 +184,10 @@ class MCLOHContainer {
} }
/// Emit all Linker Optimization Hint in one big table. /// Emit all Linker Optimization Hint in one big table.
/// Each line of the table is emitted by LOHDirective::Emit. /// Each line of the table is emitted by LOHDirective::emit.
void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
for (const MCLOHDirective &D : Directives) for (const MCLOHDirective &D : Directives)
D.Emit(ObjWriter, Layout); D.emit(ObjWriter, Layout);
} }
void reset() { void reset() {

View File

@ -1,46 +0,0 @@
//===- MCMachOSymbolFlags.h - MachO Symbol Flags ----------------*- 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 SymbolFlags used for the MachO target.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_MC_MCMACHOSYMBOLFLAGS_H
#define LLVM_MC_MCMACHOSYMBOLFLAGS_H
// These flags are mostly used in MCMachOStreamer.cpp but also needed in
// MachObjectWriter.cpp to test for Weak Definitions of symbols to emit
// the correct relocation information.
namespace llvm {
/// MachOSymbolFlags - We store the value for the 'desc' symbol field in the
/// lowest 16 bits of the implementation defined flags.
enum MachOSymbolFlags { // See <mach-o/nlist.h>.
SF_DescFlagsMask = 0xFFFF,
// Reference type flags.
SF_ReferenceTypeMask = 0x0007,
SF_ReferenceTypeUndefinedNonLazy = 0x0000,
SF_ReferenceTypeUndefinedLazy = 0x0001,
SF_ReferenceTypeDefined = 0x0002,
SF_ReferenceTypePrivateDefined = 0x0003,
SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004,
SF_ReferenceTypePrivateUndefinedLazy = 0x0005,
// Other 'desc' flags.
SF_ThumbFunc = 0x0008,
SF_NoDeadStrip = 0x0020,
SF_WeakReference = 0x0040,
SF_WeakDefinition = 0x0080,
SF_SymbolResolver = 0x0100
};
} // end namespace llvm
#endif

View File

@ -27,15 +27,11 @@ class MCMachObjectTargetWriter {
const unsigned Is64Bit : 1; const unsigned Is64Bit : 1;
const uint32_t CPUType; const uint32_t CPUType;
const uint32_t CPUSubtype; const uint32_t CPUSubtype;
// FIXME: Remove this, we should just always use it once we no longer care
// about Darwin 'as' compatibility.
const unsigned UseAggressiveSymbolFolding : 1;
unsigned LocalDifference_RIT; unsigned LocalDifference_RIT;
protected: protected:
MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_, MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_,
uint32_t CPUSubtype_, uint32_t CPUSubtype_);
bool UseAggressiveSymbolFolding_ = false);
void setLocalDifferenceRelocationType(unsigned Type) { void setLocalDifferenceRelocationType(unsigned Type) {
LocalDifference_RIT = Type; LocalDifference_RIT = Type;
@ -47,7 +43,7 @@ class MCMachObjectTargetWriter {
/// \name Lifetime Management /// \name Lifetime Management
/// @{ /// @{
virtual void reset() {}; virtual void reset() {}
/// @} /// @}
@ -55,7 +51,6 @@ class MCMachObjectTargetWriter {
/// @{ /// @{
bool is64Bit() const { return Is64Bit; } bool is64Bit() const { return Is64Bit; }
bool useAggressiveSymbolFolding() const { return UseAggressiveSymbolFolding; }
uint32_t getCPUType() const { return CPUType; } uint32_t getCPUType() const { return CPUType; }
uint32_t getCPUSubtype() const { return CPUSubtype; } uint32_t getCPUSubtype() const { return CPUSubtype; }
unsigned getLocalDifferenceRelocationType() const { unsigned getLocalDifferenceRelocationType() const {
@ -67,7 +62,7 @@ class MCMachObjectTargetWriter {
/// \name API /// \name API
/// @{ /// @{
virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, virtual void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
const MCAsmLayout &Layout, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target, const MCFixup &Fixup, MCValue Target,
@ -77,8 +72,7 @@ class MCMachObjectTargetWriter {
}; };
class MachObjectWriter : public MCObjectWriter { class MachObjectWriter : public MCObjectWriter {
/// MachSymbolData - Helper struct for containing some precomputed information /// Helper struct for containing some precomputed information on symbols.
/// on symbols.
struct MachSymbolData { struct MachSymbolData {
const MCSymbol *Symbol; const MCSymbol *Symbol;
uint64_t StringIndex; uint64_t StringIndex;
@ -104,6 +98,8 @@ class MachObjectWriter : public MCObjectWriter {
llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations; llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase; llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase;
SectionAddrMap SectionAddress;
/// @} /// @}
/// \name Symbol Table Data /// \name Symbol Table Data
/// @{ /// @{
@ -136,8 +132,6 @@ class MachObjectWriter : public MCObjectWriter {
bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
SectionAddrMap SectionAddress;
SectionAddrMap &getSectionAddressMap() { return SectionAddress; } SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
uint64_t getSectionAddress(const MCSection *Sec) const { uint64_t getSectionAddress(const MCSection *Sec) const {
@ -165,41 +159,37 @@ class MachObjectWriter : public MCObjectWriter {
/// @} /// @}
void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize, void writeHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
bool SubsectionsViaSymbols); bool SubsectionsViaSymbols);
/// WriteSegmentLoadCommand - Write a segment load command. /// Write a segment load command.
/// ///
/// \param NumSections The number of sections in this segment. /// \param NumSections The number of sections in this segment.
/// \param SectionDataSize The total size of the sections. /// \param SectionDataSize The total size of the sections.
void WriteSegmentLoadCommand(unsigned NumSections, void writeSegmentLoadCommand(unsigned NumSections, uint64_t VMSize,
uint64_t VMSize,
uint64_t SectionDataStartOffset, uint64_t SectionDataStartOffset,
uint64_t SectionDataSize); uint64_t SectionDataSize);
void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout, void writeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCSection &Sec, uint64_t FileOffset, const MCSection &Sec, uint64_t FileOffset,
uint64_t RelocationsStart, unsigned NumRelocations); uint64_t RelocationsStart, unsigned NumRelocations);
void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
uint32_t StringTableOffset, uint32_t StringTableOffset,
uint32_t StringTableSize); uint32_t StringTableSize);
void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, void writeDysymtabLoadCommand(
uint32_t NumLocalSymbols, uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols,
uint32_t FirstExternalSymbol, uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols,
uint32_t NumExternalSymbols, uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols,
uint32_t FirstUndefinedSymbol, uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols);
uint32_t NumUndefinedSymbols,
uint32_t IndirectSymbolOffset,
uint32_t NumIndirectSymbols);
void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout); void writeNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset, void writeLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
uint32_t DataSize); uint32_t DataSize);
void WriteLinkerOptionsLoadCommand(const std::vector<std::string> &Options); void writeLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
// FIXME: We really need to improve the relocation validation. Basically, we // FIXME: We really need to improve the relocation validation. Basically, we
// want to implement a separate computation which evaluates the relocation // want to implement a separate computation which evaluates the relocation
@ -226,29 +216,25 @@ class MachObjectWriter : public MCObjectWriter {
Relocations[Sec].push_back(P); Relocations[Sec].push_back(P);
} }
void RecordScatteredRelocation(const MCAssembler &Asm, void recordScatteredRelocation(const MCAssembler &Asm,
const MCAsmLayout &Layout, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target, const MCFixup &Fixup, MCValue Target,
unsigned Log2Size, unsigned Log2Size, uint64_t &FixedValue);
uint64_t &FixedValue);
void RecordTLVPRelocation(const MCAssembler &Asm, void recordTLVPRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup,
const MCFragment *Fragment, MCValue Target, uint64_t &FixedValue);
const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue);
void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup, const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, bool &IsPCRel, MCValue Target, bool &IsPCRel,
uint64_t &FixedValue) override; uint64_t &FixedValue) override;
void BindIndirectSymbols(MCAssembler &Asm); void bindIndirectSymbols(MCAssembler &Asm);
/// ComputeSymbolTable - Compute the symbol table data /// Compute the symbol table data.
/// void computeSymbolTable(MCAssembler &Asm,
void ComputeSymbolTable(MCAssembler &Asm,
std::vector<MachSymbolData> &LocalSymbolData, std::vector<MachSymbolData> &LocalSymbolData,
std::vector<MachSymbolData> &ExternalSymbolData, std::vector<MachSymbolData> &ExternalSymbolData,
std::vector<MachSymbolData> &UndefinedSymbolData); std::vector<MachSymbolData> &UndefinedSymbolData);
@ -256,19 +242,18 @@ class MachObjectWriter : public MCObjectWriter {
void computeSectionAddresses(const MCAssembler &Asm, void computeSectionAddresses(const MCAssembler &Asm,
const MCAsmLayout &Layout); const MCAsmLayout &Layout);
void ExecutePostLayoutBinding(MCAssembler &Asm, void executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) override; const MCAsmLayout &Layout) override;
bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
const MCSymbol &SymA, const MCSymbol &SymA,
const MCFragment &FB, bool InSet, const MCFragment &FB, bool InSet,
bool IsPCRel) const override; bool IsPCRel) const override;
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
}; };
/// Construct a new Mach-O writer instance.
/// \brief Construct a new Mach-O writer instance.
/// ///
/// This routine takes ownership of the target writer subclass. /// This routine takes ownership of the target writer subclass.
/// ///

View File

@ -18,28 +18,25 @@
#include "llvm/Support/CodeGen.h" #include "llvm/Support/CodeGen.h"
namespace llvm { namespace llvm {
class MCContext; class MCContext;
class MCSection; class MCSection;
class StringRef; class StringRef;
class MCObjectFileInfo { class MCObjectFileInfo {
protected: protected:
/// CommDirectiveSupportsAlignment - True if .comm supports alignment. This /// True if .comm supports alignment. This is a hack for as long as we
/// is a hack for as long as we support 10.4 Tiger, whose assembler doesn't /// support 10.4 Tiger, whose assembler doesn't support alignment on comm.
/// support alignment on comm.
bool CommDirectiveSupportsAlignment; bool CommDirectiveSupportsAlignment;
/// SupportsWeakEmptyEHFrame - True if target object file supports a /// True if target object file supports a weak_definition of constant 0 for an
/// weak_definition of constant 0 for an omitted EH frame. /// omitted EH frame.
bool SupportsWeakOmittedEHFrame; bool SupportsWeakOmittedEHFrame;
/// SupportsCompactUnwindWithoutEHFrame - True if the target object file /// True if the target object file supports emitting a compact unwind section
/// supports emitting a compact unwind section without an associated EH frame /// without an associated EH frame section.
/// section.
bool SupportsCompactUnwindWithoutEHFrame; bool SupportsCompactUnwindWithoutEHFrame;
/// PersonalityEncoding, LSDAEncoding, TTypeEncoding - Some encoding values /// Some encoding values for EH.
/// for EH.
unsigned PersonalityEncoding; unsigned PersonalityEncoding;
unsigned LSDAEncoding; unsigned LSDAEncoding;
unsigned FDECFIEncoding; unsigned FDECFIEncoding;
@ -49,16 +46,13 @@ class MCObjectFileInfo {
unsigned EHSectionType; unsigned EHSectionType;
unsigned EHSectionFlags; unsigned EHSectionFlags;
/// CompactUnwindDwarfEHFrameOnly - Compact unwind encoding indicating that we /// Compact unwind encoding indicating that we should emit only an EH frame.
/// should emit only an EH frame.
unsigned CompactUnwindDwarfEHFrameOnly; unsigned CompactUnwindDwarfEHFrameOnly;
/// Section directive for standard text. /// Section directive for standard text.
///
MCSection *TextSection; MCSection *TextSection;
/// Section directive for standard data. /// Section directive for standard data.
///
MCSection *DataSection; MCSection *DataSection;
/// Section that is default initialized to zero. /// Section that is default initialized to zero.
@ -101,7 +95,7 @@ class MCObjectFileInfo {
// can be enabled by a compiler flag. // can be enabled by a compiler flag.
MCSection *DwarfPubNamesSection; MCSection *DwarfPubNamesSection;
// DWARF5 Experimental Debug Info Sections /// DWARF5 Experimental Debug Info Sections
/// DwarfAccelNamesSection, DwarfAccelObjCSection, /// DwarfAccelNamesSection, DwarfAccelObjCSection,
/// DwarfAccelNamespaceSection, DwarfAccelTypesSection - /// DwarfAccelNamespaceSection, DwarfAccelTypesSection -
/// If we use the DWARF accelerated hash tables then we want to emit these /// If we use the DWARF accelerated hash tables then we want to emit these
@ -111,7 +105,7 @@ class MCObjectFileInfo {
MCSection *DwarfAccelNamespaceSection; MCSection *DwarfAccelNamespaceSection;
MCSection *DwarfAccelTypesSection; MCSection *DwarfAccelTypesSection;
/// These are used for the Fission separate debug information files. // These are used for the Fission separate debug information files.
MCSection *DwarfInfoDWOSection; MCSection *DwarfInfoDWOSection;
MCSection *DwarfTypesDWOSection; MCSection *DwarfTypesDWOSection;
MCSection *DwarfAbbrevDWOSection; MCSection *DwarfAbbrevDWOSection;
@ -121,32 +115,36 @@ class MCObjectFileInfo {
MCSection *DwarfStrOffDWOSection; MCSection *DwarfStrOffDWOSection;
MCSection *DwarfAddrSection; MCSection *DwarfAddrSection;
/// Sections for newer gnu pubnames and pubtypes. /// Section for newer gnu pubnames.
MCSection *DwarfGnuPubNamesSection; MCSection *DwarfGnuPubNamesSection;
/// Section for newer gnu pubtypes.
MCSection *DwarfGnuPubTypesSection; MCSection *DwarfGnuPubTypesSection;
MCSection *COFFDebugSymbolsSection; MCSection *COFFDebugSymbolsSection;
// Extra TLS Variable Data section. If the target needs to put additional /// Extra TLS Variable Data section.
// information for a TLS variable, it'll go here. ///
/// If the target needs to put additional information for a TLS variable,
/// it'll go here.
MCSection *TLSExtraDataSection; MCSection *TLSExtraDataSection;
/// Section directive for Thread Local data. ELF, MachO and COFF. /// Section directive for Thread Local data. ELF, MachO and COFF.
MCSection *TLSDataSection; // Defaults to ".tdata". MCSection *TLSDataSection; // Defaults to ".tdata".
/// Section directive for Thread Local uninitialized data. Null if this target /// Section directive for Thread Local uninitialized data.
/// doesn't support a BSS section. ELF and MachO only. ///
/// Null if this target doesn't support a BSS section. ELF and MachO only.
MCSection *TLSBSSSection; // Defaults to ".tbss". MCSection *TLSBSSSection; // Defaults to ".tbss".
/// StackMap section. /// StackMap section.
MCSection *StackMapSection; MCSection *StackMapSection;
/// EH frame section. It is initialized on demand so it can be overwritten /// EH frame section.
/// (with uniquing). ///
/// It is initialized on demand so it can be overwritten (with uniquing).
MCSection *EHFrameSection; MCSection *EHFrameSection;
/// ELF specific sections. // ELF specific sections.
///
MCSection *DataRelSection; MCSection *DataRelSection;
const MCSection *DataRelLocalSection; const MCSection *DataRelLocalSection;
MCSection *DataRelROSection; MCSection *DataRelROSection;
@ -155,17 +153,16 @@ class MCObjectFileInfo {
MCSection *MergeableConst8Section; MCSection *MergeableConst8Section;
MCSection *MergeableConst16Section; MCSection *MergeableConst16Section;
/// MachO specific sections. // MachO specific sections.
///
/// Section for thread local structure information. Contains the source code /// Section for thread local structure information.
/// name of the variable, visibility and a pointer to the initial value ///
/// (.tdata or .tbss). /// Contains the source code name of the variable, visibility and a pointer to
/// the initial value (.tdata or .tbss).
MCSection *TLSTLVSection; // Defaults to ".tlv". MCSection *TLSTLVSection; // Defaults to ".tlv".
/// TLSThreadInitSection - Section for thread local data initialization /// Section for thread local data initialization functions.
/// functions. const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func".
const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func".
MCSection *CStringSection; MCSection *CStringSection;
MCSection *UStringSection; MCSection *UStringSection;
@ -182,10 +179,10 @@ class MCObjectFileInfo {
MCSection *NonLazySymbolPointerSection; MCSection *NonLazySymbolPointerSection;
/// COFF specific sections. /// COFF specific sections.
///
MCSection *DrectveSection; MCSection *DrectveSection;
MCSection *PDataSection; MCSection *PDataSection;
MCSection *XDataSection; MCSection *XDataSection;
MCSection *SXDataSection;
public: public:
void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM,
@ -266,8 +263,7 @@ class MCObjectFileInfo {
MCSection *getStackMapSection() const { return StackMapSection; } MCSection *getStackMapSection() const { return StackMapSection; }
/// ELF specific sections. // ELF specific sections.
///
MCSection *getDataRelSection() const { return DataRelSection; } MCSection *getDataRelSection() const { return DataRelSection; }
const MCSection *getDataRelLocalSection() const { const MCSection *getDataRelLocalSection() const {
return DataRelLocalSection; return DataRelLocalSection;
@ -284,8 +280,7 @@ class MCObjectFileInfo {
return MergeableConst16Section; return MergeableConst16Section;
} }
/// MachO specific sections. // MachO specific sections.
///
const MCSection *getTLSTLVSection() const { return TLSTLVSection; } const MCSection *getTLSTLVSection() const { return TLSTLVSection; }
const MCSection *getTLSThreadInitSection() const { const MCSection *getTLSThreadInitSection() const {
return TLSThreadInitSection; return TLSThreadInitSection;
@ -316,11 +311,11 @@ class MCObjectFileInfo {
return NonLazySymbolPointerSection; return NonLazySymbolPointerSection;
} }
/// COFF specific sections. // COFF specific sections.
///
MCSection *getDrectveSection() const { return DrectveSection; } MCSection *getDrectveSection() const { return DrectveSection; }
MCSection *getPDataSection() const { return PDataSection; } MCSection *getPDataSection() const { return PDataSection; }
MCSection *getXDataSection() const { return XDataSection; } MCSection *getXDataSection() const { return XDataSection; }
MCSection *getSXDataSection() const { return SXDataSection; }
MCSection *getEHFrameSection() { MCSection *getEHFrameSection() {
if (!EHFrameSection) if (!EHFrameSection)
@ -329,13 +324,9 @@ class MCObjectFileInfo {
} }
enum Environment { IsMachO, IsELF, IsCOFF }; enum Environment { IsMachO, IsELF, IsCOFF };
Environment getObjectFileType() const { Environment getObjectFileType() const { return Env; }
return Env;
}
Reloc::Model getRelocM() const { Reloc::Model getRelocM() const { return RelocM; }
return RelocM;
}
private: private:
Environment Env; Environment Env;
@ -344,12 +335,11 @@ class MCObjectFileInfo {
MCContext *Ctx; MCContext *Ctx;
Triple TT; Triple TT;
void InitMachOMCObjectFileInfo(Triple T); void initMachOMCObjectFileInfo(Triple T);
void InitELFMCObjectFileInfo(Triple T); void initELFMCObjectFileInfo(Triple T);
void InitCOFFMCObjectFileInfo(Triple T); void initCOFFMCObjectFileInfo(Triple T);
/// InitEHFrameSection - Initialize EHFrameSection on demand. /// Initialize EHFrameSection on demand.
///
void InitEHFrameSection(); void InitEHFrameSection();
public: public:

View File

@ -35,11 +35,10 @@ class raw_pwrite_stream;
/// implementation. /// implementation.
class MCObjectStreamer : public MCStreamer { class MCObjectStreamer : public MCStreamer {
MCAssembler *Assembler; MCAssembler *Assembler;
MCSection *CurSectionData;
MCSection::iterator CurInsertionPoint; MCSection::iterator CurInsertionPoint;
bool EmitEHFrame; bool EmitEHFrame;
bool EmitDebugFrame; bool EmitDebugFrame;
SmallVector<MCSymbolData *, 2> PendingLabels; SmallVector<MCSymbol *, 2> PendingLabels;
virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0; virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0;
void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
@ -57,21 +56,17 @@ class MCObjectStreamer : public MCStreamer {
/// Object streamers require the integrated assembler. /// Object streamers require the integrated assembler.
bool isIntegratedAssemblerRequired() const override { return true; } bool isIntegratedAssemblerRequired() const override { return true; }
MCSymbolData &getOrCreateSymbolData(const MCSymbol *Symbol) {
return getAssembler().getOrCreateSymbolData(*Symbol);
}
void EmitFrames(MCAsmBackend *MAB); void EmitFrames(MCAsmBackend *MAB);
void EmitCFISections(bool EH, bool Debug) override; void EmitCFISections(bool EH, bool Debug) override;
protected: protected:
MCSection *getCurrentSectionData() const { return CurSectionData; }
MCFragment *getCurrentFragment() const; MCFragment *getCurrentFragment() const;
void insert(MCFragment *F) { void insert(MCFragment *F) {
flushPendingLabels(F); flushPendingLabels(F);
CurSectionData->getFragmentList().insert(CurInsertionPoint, F); MCSection *CurSection = getCurrentSectionOnly();
F->setParent(CurSectionData); CurSection->getFragmentList().insert(CurInsertionPoint, F);
F->setParent(CurSection);
} }
/// Get a data fragment to write into, creating a new one if the current /// Get a data fragment to write into, creating a new one if the current

View File

@ -22,18 +22,17 @@ class MCAsmLayout;
class MCAssembler; class MCAssembler;
class MCFixup; class MCFixup;
class MCFragment; class MCFragment;
class MCSymbolData;
class MCSymbolRefExpr; class MCSymbolRefExpr;
class MCValue; class MCValue;
/// MCObjectWriter - Defines the object file and target independent interfaces /// Defines the object file and target independent interfaces used by the
/// used by the assembler backend to write native file format object files. /// assembler backend to write native file format object files.
/// ///
/// The object writer contains a few callbacks used by the assembler to allow /// The object writer contains a few callbacks used by the assembler to allow
/// the object writer to modify the assembler data structures at appropriate /// the object writer to modify the assembler data structures at appropriate
/// points. Once assembly is complete, the object writer is given the /// points. Once assembly is complete, the object writer is given the
/// MCAssembler instance, which contains all the symbol and section data which /// MCAssembler instance, which contains all the symbol and section data which
/// should be emitted as part of WriteObject(). /// should be emitted as part of writeObject().
/// ///
/// The object writer also contains a number of helper methods for writing /// The object writer also contains a number of helper methods for writing
/// binary data to the output stream. /// binary data to the output stream.
@ -54,7 +53,7 @@ class MCObjectWriter {
virtual ~MCObjectWriter(); virtual ~MCObjectWriter();
/// lifetime management /// lifetime management
virtual void reset() { } virtual void reset() {}
bool isLittleEndian() const { return IsLittleEndian; } bool isLittleEndian() const { return IsLittleEndian; }
@ -63,109 +62,106 @@ class MCObjectWriter {
/// \name High-Level API /// \name High-Level API
/// @{ /// @{
/// \brief Perform any late binding of symbols (for example, to assign symbol /// Perform any late binding of symbols (for example, to assign symbol
/// indices for use when generating relocations). /// indices for use when generating relocations).
/// ///
/// This routine is called by the assembler after layout and relaxation is /// This routine is called by the assembler after layout and relaxation is
/// complete. /// complete.
virtual void ExecutePostLayoutBinding(MCAssembler &Asm, virtual void executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) = 0; const MCAsmLayout &Layout) = 0;
/// \brief Record a relocation entry. /// Record a relocation entry.
/// ///
/// This routine is called by the assembler after layout and relaxation, and /// This routine is called by the assembler after layout and relaxation, and
/// post layout binding. The implementation is responsible for storing /// post layout binding. The implementation is responsible for storing
/// information about the relocation so that it can be emitted during /// information about the relocation so that it can be emitted during
/// WriteObject(). /// writeObject().
virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target, const MCFixup &Fixup, MCValue Target,
bool &IsPCRel, uint64_t &FixedValue) = 0; bool &IsPCRel, uint64_t &FixedValue) = 0;
/// \brief Check whether the difference (A - B) between two symbol /// Check whether the difference (A - B) between two symbol references is
/// references is fully resolved. /// fully resolved.
/// ///
/// Clients are not required to answer precisely and may conservatively return /// Clients are not required to answer precisely and may conservatively return
/// false, even when a difference is fully resolved. /// false, even when a difference is fully resolved.
bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, bool isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
const MCSymbolRefExpr *A, const MCSymbolRefExpr *A,
const MCSymbolRefExpr *B, const MCSymbolRefExpr *B,
bool InSet) const; bool InSet) const;
virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
const MCSymbol &SymA, const MCSymbol &SymA,
const MCFragment &FB, const MCFragment &FB,
bool InSet, bool InSet,
bool IsPCRel) const; bool IsPCRel) const;
/// \brief True if this symbol (which is a variable) is weak. This is not /// True if this symbol (which is a variable) is weak. This is not
/// just STB_WEAK, but more generally whether or not we can evaluate /// just STB_WEAK, but more generally whether or not we can evaluate
/// past it. /// past it.
virtual bool isWeak(const MCSymbol &Sym) const; virtual bool isWeak(const MCSymbol &Sym) const;
/// \brief Write the object file. /// Write the object file.
/// ///
/// This routine is called by the assembler after layout and relaxation is /// This routine is called by the assembler after layout and relaxation is
/// complete, fixups have been evaluated and applied, and relocations /// complete, fixups have been evaluated and applied, and relocations
/// generated. /// generated.
virtual void WriteObject(MCAssembler &Asm, virtual void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0;
const MCAsmLayout &Layout) = 0;
/// @} /// @}
/// \name Binary Output /// \name Binary Output
/// @{ /// @{
void Write8(uint8_t Value) { void write8(uint8_t Value) { OS << char(Value); }
OS << char(Value);
}
void WriteLE16(uint16_t Value) { void writeLE16(uint16_t Value) {
support::endian::Writer<support::little>(OS).write(Value); support::endian::Writer<support::little>(OS).write(Value);
} }
void WriteLE32(uint32_t Value) { void writeLE32(uint32_t Value) {
support::endian::Writer<support::little>(OS).write(Value); support::endian::Writer<support::little>(OS).write(Value);
} }
void WriteLE64(uint64_t Value) { void writeLE64(uint64_t Value) {
support::endian::Writer<support::little>(OS).write(Value); support::endian::Writer<support::little>(OS).write(Value);
} }
void WriteBE16(uint16_t Value) { void writeBE16(uint16_t Value) {
support::endian::Writer<support::big>(OS).write(Value); support::endian::Writer<support::big>(OS).write(Value);
} }
void WriteBE32(uint32_t Value) { void writeBE32(uint32_t Value) {
support::endian::Writer<support::big>(OS).write(Value); support::endian::Writer<support::big>(OS).write(Value);
} }
void WriteBE64(uint64_t Value) { void writeBE64(uint64_t Value) {
support::endian::Writer<support::big>(OS).write(Value); support::endian::Writer<support::big>(OS).write(Value);
} }
void Write16(uint16_t Value) { void write16(uint16_t Value) {
if (IsLittleEndian) if (IsLittleEndian)
WriteLE16(Value); writeLE16(Value);
else else
WriteBE16(Value); writeBE16(Value);
} }
void Write32(uint32_t Value) { void write32(uint32_t Value) {
if (IsLittleEndian) if (IsLittleEndian)
WriteLE32(Value); writeLE32(Value);
else else
WriteBE32(Value); writeBE32(Value);
} }
void Write64(uint64_t Value) { void write64(uint64_t Value) {
if (IsLittleEndian) if (IsLittleEndian)
WriteLE64(Value); writeLE64(Value);
else else
WriteBE64(Value); writeBE64(Value);
} }
void WriteZeros(unsigned N) { void WriteZeros(unsigned N) {
const char Zeros[16] = { 0 }; const char Zeros[16] = {0};
for (unsigned i = 0, e = N / 16; i != e; ++i) for (unsigned i = 0, e = N / 16; i != e; ++i)
OS << StringRef(Zeros, 16); OS << StringRef(Zeros, 16);
@ -173,22 +169,23 @@ class MCObjectWriter {
OS << StringRef(Zeros, N % 16); OS << StringRef(Zeros, N % 16);
} }
void WriteBytes(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) { void writeBytes(const SmallVectorImpl<char> &ByteVec,
WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize); unsigned ZeroFillSize = 0) {
writeBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
} }
void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) { void writeBytes(StringRef Str, unsigned ZeroFillSize = 0) {
// TODO: this version may need to go away once all fragment contents are // TODO: this version may need to go away once all fragment contents are
// converted to SmallVector<char, N> // converted to SmallVector<char, N>
assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) && assert(
"data size greater than fill size, unexpected large write will occur"); (ZeroFillSize == 0 || Str.size() <= ZeroFillSize) &&
"data size greater than fill size, unexpected large write will occur");
OS << Str; OS << Str;
if (ZeroFillSize) if (ZeroFillSize)
WriteZeros(ZeroFillSize - Str.size()); WriteZeros(ZeroFillSize - Str.size());
} }
/// @} /// @}
}; };
} // End llvm namespace } // End llvm namespace

View File

@ -73,11 +73,13 @@ class MCSection {
/// \brief We've seen a bundle_lock directive but not its first instruction /// \brief We've seen a bundle_lock directive but not its first instruction
/// yet. /// yet.
bool BundleGroupBeforeFirstInst = false; unsigned BundleGroupBeforeFirstInst : 1;
/// Whether this section has had instructions emitted into it. /// Whether this section has had instructions emitted into it.
unsigned HasInstructions : 1; unsigned HasInstructions : 1;
unsigned IsRegistered : 1;
FragmentListType Fragments; FragmentListType Fragments;
/// Mapping from subsection number to insertion point for subsection numbers /// Mapping from subsection number to insertion point for subsection numbers
@ -130,6 +132,9 @@ class MCSection {
bool hasInstructions() const { return HasInstructions; } bool hasInstructions() const { return HasInstructions; }
void setHasInstructions(bool Value) { HasInstructions = Value; } void setHasInstructions(bool Value) { HasInstructions = Value; }
bool isRegistered() const { return IsRegistered; }
void setIsRegistered(bool Value) { IsRegistered = Value; }
MCSection::FragmentListType &getFragmentList() { return Fragments; } MCSection::FragmentListType &getFragmentList() { return Fragments; }
const MCSection::FragmentListType &getFragmentList() const { const MCSection::FragmentListType &getFragmentList() const {
return const_cast<MCSection *>(this)->getFragmentList(); return const_cast<MCSection *>(this)->getFragmentList();

View File

@ -16,7 +16,7 @@
#include "llvm/ADT/Twine.h" #include "llvm/ADT/Twine.h"
#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolELF.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ELF.h" #include "llvm/Support/ELF.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -46,7 +46,7 @@ class MCSectionELF : public MCSection {
/// section does not contain fixed-sized entries 'EntrySize' will be 0. /// section does not contain fixed-sized entries 'EntrySize' will be 0.
unsigned EntrySize; unsigned EntrySize;
const MCSymbol *Group; const MCSymbolELF *Group;
/// Depending on the type of the section this is sh_link or sh_info. /// Depending on the type of the section this is sh_link or sh_info.
const MCSectionELF *Associated; const MCSectionELF *Associated;
@ -54,11 +54,14 @@ class MCSectionELF : public MCSection {
private: private:
friend class MCContext; friend class MCContext;
MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K, MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K,
unsigned entrySize, const MCSymbol *group, unsigned UniqueID, unsigned entrySize, const MCSymbolELF *group, unsigned UniqueID,
MCSymbol *Begin, const MCSectionELF *Associated) MCSymbol *Begin, const MCSectionELF *Associated)
: MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type), : MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type),
Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group), Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group),
Associated(Associated) {} Associated(Associated) {
if (Group)
Group->setIsSignature();
}
~MCSectionELF() override; ~MCSectionELF() override;
void setSectionName(StringRef Name) { SectionName = Name; } void setSectionName(StringRef Name) { SectionName = Name; }
@ -73,7 +76,7 @@ class MCSectionELF : public MCSection {
unsigned getType() const { return Type; } unsigned getType() const { return Type; }
unsigned getFlags() const { return Flags; } unsigned getFlags() const { return Flags; }
unsigned getEntrySize() const { return EntrySize; } unsigned getEntrySize() const { return EntrySize; }
const MCSymbol *getGroup() const { return Group; } const MCSymbolELF *getGroup() const { return Group; }
void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS,
const MCExpr *Subsection) const override; const MCExpr *Subsection) const override;

View File

@ -34,6 +34,7 @@ class MCInstPrinter;
class MCSection; class MCSection;
class MCStreamer; class MCStreamer;
class MCSymbol; class MCSymbol;
class MCSymbolELF;
class MCSymbolRefExpr; class MCSymbolRefExpr;
class MCSubtargetInfo; class MCSubtargetInfo;
class StringRef; class StringRef;
@ -272,6 +273,7 @@ class MCStreamer {
return SectionStack.back().first; return SectionStack.back().first;
return MCSectionSubPair(); return MCSectionSubPair();
} }
MCSection *getCurrentSectionOnly() const { return getCurrentSection().first; }
/// \brief Return the previous section that the streamer is emitting code to. /// \brief Return the previous section that the streamer is emitting code to.
MCSectionSubPair getPreviousSection() const { MCSectionSubPair getPreviousSection() const {
@ -305,11 +307,15 @@ class MCStreamer {
bool PopSection() { bool PopSection() {
if (SectionStack.size() <= 1) if (SectionStack.size() <= 1)
return false; return false;
MCSectionSubPair oldSection = SectionStack.pop_back_val().first; auto I = SectionStack.end();
MCSectionSubPair curSection = SectionStack.back().first; --I;
MCSectionSubPair OldSection = I->first;
--I;
MCSectionSubPair NewSection = I->first;
if (oldSection != curSection) if (OldSection != NewSection)
ChangeSection(curSection.first, curSection.second); ChangeSection(NewSection.first, NewSection.second);
SectionStack.pop_back();
return true; return true;
} }
@ -433,6 +439,8 @@ class MCStreamer {
/// \brief Marks the end of the symbol definition. /// \brief Marks the end of the symbol definition.
virtual void EndCOFFSymbolDef(); virtual void EndCOFFSymbolDef();
virtual void EmitCOFFSafeSEH(MCSymbol const *Symbol);
/// \brief Emits a COFF section index. /// \brief Emits a COFF section index.
/// ///
/// \param Symbol - Symbol the section number relocation should point to. /// \param Symbol - Symbol the section number relocation should point to.
@ -447,7 +455,7 @@ class MCStreamer {
/// ///
/// This corresponds to an assembler statement such as: /// This corresponds to an assembler statement such as:
/// .size symbol, expression /// .size symbol, expression
virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); virtual void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value);
/// \brief Emit a Linker Optimization Hint (LOH) directive. /// \brief Emit a Linker Optimization Hint (LOH) directive.
/// \param Args - Arguments of the LOH. /// \param Args - Arguments of the LOH.

View File

@ -73,7 +73,9 @@ class MCSubtargetInfo {
/// setFeatureBits - Set the feature bits. /// setFeatureBits - Set the feature bits.
/// ///
void setFeatureBits(FeatureBitset& FeatureBits_) { FeatureBits = FeatureBits_; } void setFeatureBits(const FeatureBitset &FeatureBits_) {
FeatureBits = FeatureBits_;
}
/// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with /// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with
/// feature string). Recompute feature bits and scheduling model. /// feature string). Recompute feature bits and scheduling model.
@ -94,6 +96,10 @@ class MCSubtargetInfo {
/// feature bits. This version will also change all implied bits. /// feature bits. This version will also change all implied bits.
FeatureBitset ToggleFeature(StringRef FS); FeatureBitset ToggleFeature(StringRef FS);
/// Apply a feature flag and return the re-computed feature bits, including
/// all feature bits implied by the flag.
FeatureBitset ApplyFeatureFlag(StringRef FS);
/// getSchedModelForCPU - Get the machine model of a CPU. /// getSchedModelForCPU - Get the machine model of a CPU.
/// ///
MCSchedModel getSchedModelForCPU(StringRef CPU) const; MCSchedModel getSchedModelForCPU(StringRef CPU) const;

View File

@ -14,12 +14,14 @@
#ifndef LLVM_MC_MCSYMBOL_H #ifndef LLVM_MC_MCSYMBOL_H
#define LLVM_MC_MCSYMBOL_H #define LLVM_MC_MCSYMBOL_H
#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCExpr.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
namespace llvm { namespace llvm {
class MCAsmInfo;
class MCExpr; class MCExpr;
class MCSymbol; class MCSymbol;
class MCFragment; class MCFragment;
@ -27,109 +29,6 @@ class MCSection;
class MCContext; class MCContext;
class raw_ostream; class raw_ostream;
// TODO: Merge completely with MCSymbol.
class MCSymbolData {
/// Fragment - The fragment this symbol's value is relative to, if any. Also
/// stores if this symbol is visible outside this translation unit (bit 0) or
/// if it is private extern (bit 1).
PointerIntPair<MCFragment *, 2> Fragment;
union {
/// Offset - The offset to apply to the fragment address to form this
/// symbol's value.
uint64_t Offset;
/// CommonSize - The size of the symbol, if it is 'common'.
uint64_t CommonSize;
};
/// SymbolSize - An expression describing how to calculate the size of
/// a symbol. If a symbol has no size this field will be NULL.
const MCExpr *SymbolSize = nullptr;
/// CommonAlign - The alignment of the symbol, if it is 'common', or -1.
//
// FIXME: Pack this in with other fields?
unsigned CommonAlign = -1U;
/// Flags - The Flags field is used by object file implementations to store
/// additional per symbol information which is not easily classified.
uint32_t Flags = 0;
public:
MCSymbolData() { Offset = 0; }
MCFragment *getFragment() const { return Fragment.getPointer(); }
void setFragment(MCFragment *Value) { Fragment.setPointer(Value); }
uint64_t getOffset() const {
assert(!isCommon());
return Offset;
}
void setOffset(uint64_t Value) {
assert(!isCommon());
Offset = Value;
}
/// @}
/// \name Symbol Attributes
/// @{
bool isExternal() const { return Fragment.getInt() & 1; }
void setExternal(bool Value) {
Fragment.setInt((Fragment.getInt() & ~1) | unsigned(Value));
}
bool isPrivateExtern() const { return Fragment.getInt() & 2; }
void setPrivateExtern(bool Value) {
Fragment.setInt((Fragment.getInt() & ~2) | (unsigned(Value) << 1));
}
/// isCommon - Is this a 'common' symbol.
bool isCommon() const { return CommonAlign != -1U; }
/// setCommon - Mark this symbol as being 'common'.
///
/// \param Size - The size of the symbol.
/// \param Align - The alignment of the symbol.
void setCommon(uint64_t Size, unsigned Align) {
assert(getOffset() == 0);
CommonSize = Size;
CommonAlign = Align;
}
/// getCommonSize - Return the size of a 'common' symbol.
uint64_t getCommonSize() const {
assert(isCommon() && "Not a 'common' symbol!");
return CommonSize;
}
void setSize(const MCExpr *SS) { SymbolSize = SS; }
const MCExpr *getSize() const { return SymbolSize; }
/// getCommonAlignment - Return the alignment of a 'common' symbol.
unsigned getCommonAlignment() const {
assert(isCommon() && "Not a 'common' symbol!");
return CommonAlign;
}
/// getFlags - Get the (implementation defined) symbol flags.
uint32_t getFlags() const { return Flags; }
/// setFlags - Set the (implementation defined) symbol flags.
void setFlags(uint32_t Value) { Flags = Value; }
/// modifyFlags - Modify the flags via a mask
void modifyFlags(uint32_t Value, uint32_t Mask) {
Flags = (Flags & ~Mask) | Value;
}
/// @}
void dump() const;
};
/// MCSymbol - Instances of this class represent a symbol name in the MC file, /// MCSymbol - Instances of this class represent a symbol name in the MC file,
/// and MCSymbols are created and uniqued by the MCContext class. MCSymbols /// and MCSymbols are created and uniqued by the MCContext class. MCSymbols
/// should only be constructed with valid names for the object file. /// should only be constructed with valid names for the object file.
@ -138,6 +37,16 @@ class MCSymbolData {
/// Section member is set to indicate what section it lives in. Otherwise, if /// Section member is set to indicate what section it lives in. Otherwise, if
/// it is a reference to an external entity, it has a null section. /// it is a reference to an external entity, it has a null section.
class MCSymbol { class MCSymbol {
protected:
/// The kind of the symbol. If it is any value other than unset then this
/// class is actually one of the appropriate subclasses of MCSymbol.
enum SymbolKind {
SymbolKindUnset,
SymbolKindCOFF,
SymbolKindELF,
SymbolKindMachO,
};
// Special sentinal value for the absolute pseudo section. // Special sentinal value for the absolute pseudo section.
// //
// FIXME: Use a PointerInt wrapper for this? // FIXME: Use a PointerInt wrapper for this?
@ -147,10 +56,18 @@ class MCSymbol {
/// held by the StringMap that lives in MCContext. /// held by the StringMap that lives in MCContext.
const StringMapEntry<bool> *Name; const StringMapEntry<bool> *Name;
/// The section the symbol is defined in. This is null for undefined symbols, /// If a symbol has a Fragment, the section is implied, so we only need
/// and the special AbsolutePseudoSection value for absolute symbols. If this /// one pointer.
/// is a variable symbol, this caches the variable value's section. /// FIXME: We might be able to simplify this by having the asm streamer create
mutable MCSection *Section; /// dummy fragments.
/// If this is a section, then it gives the symbol is defined in. This is null
/// for undefined symbols, and the special AbsolutePseudoSection value for
/// absolute symbols. If this is a variable symbol, this caches the variable
/// value's section.
///
/// If this is a fragment, then it gives the fragment this symbol's value is
/// relative to, if any.
mutable PointerUnion<MCSection *, MCFragment *> SectionOrFragment;
/// Value - If non-null, the value for a variable symbol. /// Value - If non-null, the value for a variable symbol.
const MCExpr *Value; const MCExpr *Value;
@ -166,46 +83,68 @@ class MCSymbol {
/// IsUsed - True if this symbol has been used. /// IsUsed - True if this symbol has been used.
mutable unsigned IsUsed : 1; mutable unsigned IsUsed : 1;
mutable bool HasData : 1; mutable bool IsRegistered : 1;
/// This symbol is visible outside this translation unit.
mutable unsigned IsExternal : 1;
/// This symbol is private extern.
mutable unsigned IsPrivateExtern : 1;
/// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is
/// unsigned to avoid sign extension and achieve better bitpacking with MSVC.
unsigned Kind : 2;
/// Index field, for use by the object file implementation. /// Index field, for use by the object file implementation.
mutable uint64_t Index : 60; mutable uint32_t Index = 0;
mutable MCSymbolData Data; union {
/// The offset to apply to the fragment address to form this symbol's value.
uint64_t Offset;
private: // MCContext creates and uniques these. /// The size of the symbol, if it is 'common'.
uint64_t CommonSize;
};
/// The alignment of the symbol, if it is 'common', or -1.
//
// FIXME: Pack this in with other fields?
unsigned CommonAlign = -1U;
/// The Flags field is used by object file implementations to store
/// additional per symbol information which is not easily classified.
mutable uint32_t Flags = 0;
protected: // MCContext creates and uniques these.
friend class MCExpr; friend class MCExpr;
friend class MCContext; friend class MCContext;
MCSymbol(const StringMapEntry<bool> *Name, bool isTemporary) MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary)
: Name(Name), Section(nullptr), Value(nullptr), IsTemporary(isTemporary), : Name(Name), Value(nullptr), IsTemporary(isTemporary),
IsRedefinable(false), IsUsed(false), HasData(false), Index(0) {} IsRedefinable(false), IsUsed(false), IsRegistered(false),
IsExternal(false), IsPrivateExtern(false),
Kind(Kind) {
Offset = 0;
}
private:
MCSymbol(const MCSymbol &) = delete; MCSymbol(const MCSymbol &) = delete;
void operator=(const MCSymbol &) = delete; void operator=(const MCSymbol &) = delete;
MCSection *getSectionPtr() const { MCSection *getSectionPtr() const {
if (MCFragment *F = getFragment())
return F->getParent();
assert(!SectionOrFragment.is<MCFragment *>() && "Section or null expected");
MCSection *Section = SectionOrFragment.dyn_cast<MCSection *>();
if (Section || !Value) if (Section || !Value)
return Section; return Section;
return Section = Value->FindAssociatedSection(); return Section = Value->findAssociatedSection();
} }
public: public:
/// getName - Get the symbol name. /// getName - Get the symbol name.
StringRef getName() const { return Name ? Name->first() : ""; } StringRef getName() const { return Name ? Name->first() : ""; }
bool hasData() const { return HasData; } bool isRegistered() const { return IsRegistered; }
void setIsRegistered(bool Value) const { IsRegistered = Value; }
/// Get associated symbol data.
MCSymbolData &getData() const {
assert(HasData && "Missing symbol data!");
return Data;
}
/// Initialize symbol data.
///
/// Nothing really to do here, but this is enables an assertion that \a
/// MCAssembler::getOrCreateSymbolData() has actually been called before
/// anyone calls \a getData().
void initializeData() const { HasData = true; }
/// \name Accessors /// \name Accessors
/// @{ /// @{
@ -225,7 +164,7 @@ class MCSymbol {
void redefineIfPossible() { void redefineIfPossible() {
if (IsRedefinable) { if (IsRedefinable) {
Value = nullptr; Value = nullptr;
Section = nullptr; SectionOrFragment = nullptr;
IsRedefinable = false; IsRedefinable = false;
} }
} }
@ -258,11 +197,20 @@ class MCSymbol {
/// Mark the symbol as defined in the section \p S. /// Mark the symbol as defined in the section \p S.
void setSection(MCSection &S) { void setSection(MCSection &S) {
assert(!isVariable() && "Cannot set section of variable"); assert(!isVariable() && "Cannot set section of variable");
Section = &S; assert(!SectionOrFragment.is<MCFragment *>() && "Section or null expected");
SectionOrFragment = &S;
} }
/// setUndefined - Mark the symbol as undefined. /// Mark the symbol as undefined.
void setUndefined() { Section = nullptr; } void setUndefined() {
SectionOrFragment = nullptr;
}
bool isELF() const { return Kind == SymbolKindELF; }
bool isCOFF() const { return Kind == SymbolKindCOFF; }
bool isMachO() const { return Kind == SymbolKindMachO; }
/// @} /// @}
/// \name Variable Symbols /// \name Variable Symbols
@ -283,27 +231,98 @@ class MCSymbol {
/// @} /// @}
/// Get the (implementation defined) index. /// Get the (implementation defined) index.
uint64_t getIndex() const { uint32_t getIndex() const {
assert(HasData && "Uninitialized symbol data");
return Index; return Index;
} }
/// Set the (implementation defined) index. /// Set the (implementation defined) index.
void setIndex(uint64_t Value) const { void setIndex(uint32_t Value) const {
assert(HasData && "Uninitialized symbol data");
assert(!(Value >> 60) && "Not enough bits for value");
Index = Value; Index = Value;
} }
uint64_t getOffset() const {
assert(!isCommon());
return Offset;
}
void setOffset(uint64_t Value) {
assert(!isCommon());
Offset = Value;
}
/// Return the size of a 'common' symbol.
uint64_t getCommonSize() const {
assert(isCommon() && "Not a 'common' symbol!");
return CommonSize;
}
/// Mark this symbol as being 'common'.
///
/// \param Size - The size of the symbol.
/// \param Align - The alignment of the symbol.
void setCommon(uint64_t Size, unsigned Align) {
assert(getOffset() == 0);
CommonSize = Size;
CommonAlign = Align;
}
/// Return the alignment of a 'common' symbol.
unsigned getCommonAlignment() const {
assert(isCommon() && "Not a 'common' symbol!");
return CommonAlign;
}
/// Declare this symbol as being 'common'.
///
/// \param Size - The size of the symbol.
/// \param Align - The alignment of the symbol.
/// \return True if symbol was already declared as a different type
bool declareCommon(uint64_t Size, unsigned Align) {
assert(isCommon() || getOffset() == 0);
if(isCommon()) {
if(CommonSize != Size || CommonAlign != Align)
return true;
} else
setCommon(Size, Align);
return false;
}
/// Is this a 'common' symbol.
bool isCommon() const { return CommonAlign != -1U; }
MCFragment *getFragment() const {
return SectionOrFragment.dyn_cast<MCFragment *>();
}
void setFragment(MCFragment *Value) const {
SectionOrFragment = Value;
}
bool isExternal() const { return IsExternal; }
void setExternal(bool Value) const { IsExternal = Value; }
bool isPrivateExtern() const { return IsPrivateExtern; }
void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
/// print - Print the value to the stream \p OS. /// print - Print the value to the stream \p OS.
void print(raw_ostream &OS) const; void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
/// dump - Print the value to stderr. /// dump - Print the value to stderr.
void dump() const; void dump() const;
protected:
/// Get the (implementation defined) symbol flags.
uint32_t getFlags() const { return Flags; }
/// Set the (implementation defined) symbol flags.
void setFlags(uint32_t Value) const { Flags = Value; }
/// Modify the flags via a mask
void modifyFlags(uint32_t Value, uint32_t Mask) const {
Flags = (Flags & ~Mask) | Value;
}
}; };
inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
Sym.print(OS); Sym.print(OS, nullptr);
return OS; return OS;
} }
} // end namespace llvm } // end namespace llvm

View File

@ -0,0 +1,64 @@
//===- MCSymbolCOFF.h - ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_MC_MCSYMBOLCOFF_H
#define LLVM_MC_MCSYMBOLCOFF_H
#include "llvm/MC/MCSymbol.h"
namespace llvm {
class MCSymbolCOFF : public MCSymbol {
/// This corresponds to the e_type field of the COFF symbol.
mutable uint16_t Type;
enum SymbolFlags : uint16_t {
SF_ClassMask = 0x00FF,
SF_ClassShift = 0,
SF_WeakExternal = 0x0100,
SF_SafeSEH = 0x0200,
};
public:
MCSymbolCOFF(const StringMapEntry<bool> *Name, bool isTemporary)
: MCSymbol(SymbolKindCOFF, Name, isTemporary), Type(0) {}
uint16_t getType() const {
return Type;
}
void setType(uint16_t Ty) const {
Type = Ty;
}
uint16_t getClass() const {
return (getFlags() & SF_ClassMask) >> SF_ClassShift;
}
void setClass(uint16_t StorageClass) const {
modifyFlags(StorageClass << SF_ClassShift, SF_ClassMask);
}
bool isWeakExternal() const {
return getFlags() & SF_WeakExternal;
}
void setIsWeakExternal() const {
modifyFlags(SF_WeakExternal, SF_WeakExternal);
}
bool isSafeSEH() const {
return getFlags() & SF_SafeSEH;
}
void setIsSafeSEH() const {
modifyFlags(SF_SafeSEH, SF_SafeSEH);
}
static bool classof(const MCSymbol *S) { return S->isCOFF(); }
};
}
#endif

View File

@ -0,0 +1,57 @@
//===- MCSymbolELF.h - -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_MC_MCSYMBOLELF_H
#define LLVM_MC_MCSYMBOLELF_H
#include "llvm/MC/MCSymbol.h"
namespace llvm {
class MCSymbolELF : public MCSymbol {
/// An expression describing how to calculate the size of a symbol. If a
/// symbol has no size this field will be NULL.
const MCExpr *SymbolSize = nullptr;
public:
MCSymbolELF(const StringMapEntry<bool> *Name, bool isTemporary)
: MCSymbol(SymbolKindELF, Name, isTemporary) {}
void setSize(const MCExpr *SS) { SymbolSize = SS; }
const MCExpr *getSize() const { return SymbolSize; }
void setVisibility(unsigned Visibility);
unsigned getVisibility() const;
void setOther(unsigned Other);
unsigned getOther() const;
void setType(unsigned Type) const;
unsigned getType() const;
void setBinding(unsigned Binding) const;
unsigned getBinding() const;
bool isBindingSet() const;
void setUsedInReloc() const;
bool isUsedInReloc() const;
void setIsWeakrefUsedInReloc() const;
bool isWeakrefUsedInReloc() const;
void setIsSignature() const;
bool isSignature() const;
static bool classof(const MCSymbol *S) { return S->isELF(); }
private:
void setIsBindingSet() const;
};
}
#endif

View File

@ -0,0 +1,123 @@
//===- MCSymbolMachO.h - ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_MC_MCSYMBOLMACHO_H
#define setIsWeakExternal
#include "llvm/MC/MCSymbol.h"
namespace llvm {
class MCSymbolMachO : public MCSymbol {
/// \brief We store the value for the 'desc' symbol field in the
/// lowest 16 bits of the implementation defined flags.
enum MachOSymbolFlags : uint16_t { // See <mach-o/nlist.h>.
SF_DescFlagsMask = 0xFFFF,
// Reference type flags.
SF_ReferenceTypeMask = 0x0007,
SF_ReferenceTypeUndefinedNonLazy = 0x0000,
SF_ReferenceTypeUndefinedLazy = 0x0001,
SF_ReferenceTypeDefined = 0x0002,
SF_ReferenceTypePrivateDefined = 0x0003,
SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004,
SF_ReferenceTypePrivateUndefinedLazy = 0x0005,
// Other 'desc' flags.
SF_ThumbFunc = 0x0008,
SF_NoDeadStrip = 0x0020,
SF_WeakReference = 0x0040,
SF_WeakDefinition = 0x0080,
SF_SymbolResolver = 0x0100,
// Common alignment
SF_CommonAlignmentMask = 0xF0FF,
SF_CommonAlignmentShift = 8
};
public:
MCSymbolMachO(const StringMapEntry<bool> *Name, bool isTemporary)
: MCSymbol(SymbolKindMachO, Name, isTemporary) {}
// Reference type methods.
void clearReferenceType() const {
modifyFlags(0, SF_ReferenceTypeMask);
}
void setReferenceTypeUndefinedLazy(bool Value) const {
modifyFlags(Value ? SF_ReferenceTypeUndefinedLazy : 0,
SF_ReferenceTypeUndefinedLazy);
}
// Other 'desc' methods.
void setThumbFunc() const {
modifyFlags(SF_ThumbFunc, SF_ThumbFunc);
}
bool isNoDeadStrip() const {
return getFlags() & SF_NoDeadStrip;
}
void setNoDeadStrip() const {
modifyFlags(SF_NoDeadStrip, SF_NoDeadStrip);
}
bool isWeakReference() const {
return getFlags() & SF_WeakReference;
}
void setWeakReference() const {
modifyFlags(SF_WeakReference, SF_WeakReference);
}
bool isWeakDefinition() const {
return getFlags() & SF_WeakDefinition;
}
void setWeakDefinition() const {
modifyFlags(SF_WeakDefinition, SF_WeakDefinition);
}
bool isSymbolResolver() const {
return getFlags() & SF_SymbolResolver;
}
void setSymbolResolver() const {
modifyFlags(SF_SymbolResolver, SF_SymbolResolver);
}
void setDesc(unsigned Value) const {
assert(Value == (Value & SF_DescFlagsMask) &&
"Invalid .desc value!");
setFlags(Value & SF_DescFlagsMask);
}
/// \brief Get the encoded value of the flags as they will be emitted in to
/// the MachO binary
uint16_t getEncodedFlags() const {
uint16_t Flags = getFlags();
// Common alignment is packed into the 'desc' bits.
if (isCommon()) {
if (unsigned Align = getCommonAlignment()) {
unsigned Log2Size = Log2_32(Align);
assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
if (Log2Size > 15)
report_fatal_error("invalid 'common' alignment '" +
Twine(Align) + "' for '" + getName() + "'",
false);
Flags = (Flags & SF_CommonAlignmentMask) |
(Log2Size << SF_CommonAlignmentShift);
}
}
return Flags;
}
static bool classof(const MCSymbol *S) { return S->isMachO(); }
};
}
#endif

View File

@ -50,9 +50,9 @@ class MCWinCOFFStreamer : public MCObjectStreamer {
void EmitCOFFSymbolStorageClass(int StorageClass) override; void EmitCOFFSymbolStorageClass(int StorageClass) override;
void EmitCOFFSymbolType(int Type) override; void EmitCOFFSymbolType(int Type) override;
void EndCOFFSymbolDef() override; void EndCOFFSymbolDef() override;
void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
void EmitCOFFSecRel32(MCSymbol const *Symbol) override; void EmitCOFFSecRel32(MCSymbol const *Symbol) override;
void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override; unsigned ByteAlignment) override;
void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,

View File

@ -103,6 +103,10 @@ class SubtargetFeatures {
FeatureBitset ToggleFeature(FeatureBitset Bits, StringRef String, FeatureBitset ToggleFeature(FeatureBitset Bits, StringRef String,
ArrayRef<SubtargetFeatureKV> FeatureTable); ArrayRef<SubtargetFeatureKV> FeatureTable);
/// Apply the feature flag and return the newly updated feature bits.
FeatureBitset ApplyFeatureFlag(FeatureBitset Bits, StringRef Feature,
ArrayRef<SubtargetFeatureKV> FeatureTable);
/// Get feature bits of a CPU. /// Get feature bits of a CPU.
FeatureBitset getFeatureBits(StringRef CPU, FeatureBitset getFeatureBits(StringRef CPU,
ArrayRef<SubtargetFeatureKV> CPUTable, ArrayRef<SubtargetFeatureKV> CPUTable,

View File

@ -0,0 +1,51 @@
//===- ArchiveWriter.h - ar archive file format writer ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Declares the writeArchive function for writing an archive file.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_ARCHIVEWRITER_H
#define LLVM_OBJECT_ARCHIVEWRITER_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Archive.h"
#include "llvm/Support/FileSystem.h"
namespace llvm {
class NewArchiveIterator {
bool IsNewMember;
StringRef Name;
object::Archive::child_iterator OldI;
StringRef NewFilename;
public:
NewArchiveIterator(object::Archive::child_iterator I, StringRef Name);
NewArchiveIterator(StringRef I, StringRef Name);
NewArchiveIterator();
bool isNewMember() const;
StringRef getName() const;
object::Archive::child_iterator getOld() const;
StringRef getNew() const;
llvm::ErrorOr<int> getFD(sys::fs::file_status &NewStatus) const;
const sys::fs::file_status &getStatus() const;
};
std::pair<StringRef, std::error_code>
writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
bool WriteSymtab);
}
#endif

View File

@ -613,7 +613,7 @@ class COFFObjectFile : public ObjectFile {
StringRef &Res) const override; StringRef &Res) const override;
std::error_code getSymbolAddress(DataRefImpl Symb, std::error_code getSymbolAddress(DataRefImpl Symb,
uint64_t &Res) const override; uint64_t &Res) const override;
std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; uint64_t getSymbolSize(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override;
std::error_code getSymbolType(DataRefImpl Symb, std::error_code getSymbolType(DataRefImpl Symb,
SymbolRef::Type &Res) const override; SymbolRef::Type &Res) const override;
@ -647,10 +647,6 @@ class COFFObjectFile : public ObjectFile {
std::error_code std::error_code
getRelocationTypeName(DataRefImpl Rel, getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const override; SmallVectorImpl<char> &Result) const override;
std::error_code
getRelocationValueString(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const override;
public: public:
COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); COFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_begin_impl() const override;
@ -699,7 +695,7 @@ class COFFObjectFile : public ObjectFile {
return object_error::parse_failed; return object_error::parse_failed;
Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index; Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index;
return object_error::success; return std::error_code();
} }
ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const { ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const {
if (SymbolTable16) { if (SymbolTable16) {
@ -722,7 +718,7 @@ class COFFObjectFile : public ObjectFile {
if (std::error_code EC = s.getError()) if (std::error_code EC = s.getError())
return EC; return EC;
Res = reinterpret_cast<const T *>(s->getRawPtr()); Res = reinterpret_cast<const T *>(s->getRawPtr());
return object_error::success; return std::error_code();
} }
std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const; std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;

View File

@ -318,7 +318,7 @@ class ELFFile {
std::pair<const Elf_Shdr *, const Elf_Sym *> std::pair<const Elf_Shdr *, const Elf_Sym *>
getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const; getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const;
ELFFile(StringRef Object, std::error_code &ec); ELFFile(StringRef Object, std::error_code &EC);
bool isMipsELF64() const { bool isMipsELF64() const {
return Header->e_machine == ELF::EM_MIPS && return Header->e_machine == ELF::EM_MIPS &&
@ -423,12 +423,10 @@ class ELFFile {
StringRef getLoadName() const; StringRef getLoadName() const;
}; };
// Use an alignment of 2 for the typedefs since that is the worst case for typedef ELFFile<ELFType<support::little, false>> ELF32LEFile;
// ELF files in archives. typedef ELFFile<ELFType<support::little, true>> ELF64LEFile;
typedef ELFFile<ELFType<support::little, 2, false> > ELF32LEFile; typedef ELFFile<ELFType<support::big, false>> ELF32BEFile;
typedef ELFFile<ELFType<support::little, 2, true> > ELF64LEFile; typedef ELFFile<ELFType<support::big, true>> ELF64BEFile;
typedef ELFFile<ELFType<support::big, 2, false> > ELF32BEFile;
typedef ELFFile<ELFType<support::big, 2, true> > ELF64BEFile;
// Iterate through the version definitions, and place each Elf_Verdef // Iterate through the version definitions, and place each Elf_Verdef
// in the VersionMap according to its index. // in the VersionMap according to its index.
@ -622,7 +620,7 @@ typename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const {
} }
template <class ELFT> template <class ELFT>
ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &ec) ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
: Buf(Object), SectionHeaderTable(nullptr), dot_shstrtab_sec(nullptr), : Buf(Object), SectionHeaderTable(nullptr), dot_shstrtab_sec(nullptr),
dot_strtab_sec(nullptr), dot_symtab_sec(nullptr), dot_strtab_sec(nullptr), dot_symtab_sec(nullptr),
SymbolTableSectionHeaderIndex(nullptr), dot_gnu_version_sec(nullptr), SymbolTableSectionHeaderIndex(nullptr), dot_gnu_version_sec(nullptr),
@ -630,9 +628,11 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &ec)
dt_soname(nullptr) { dt_soname(nullptr) {
const uint64_t FileSize = Buf.size(); const uint64_t FileSize = Buf.size();
if (sizeof(Elf_Ehdr) > FileSize) if (sizeof(Elf_Ehdr) > FileSize) {
// FIXME: Proper error handling. // File too short!
report_fatal_error("File too short!"); EC = object_error::parse_failed;
return;
}
Header = reinterpret_cast<const Elf_Ehdr *>(base()); Header = reinterpret_cast<const Elf_Ehdr *>(base());
@ -641,40 +641,50 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &ec)
const uint64_t SectionTableOffset = Header->e_shoff; const uint64_t SectionTableOffset = Header->e_shoff;
if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) {
// FIXME: Proper error handling. // Section header table goes past end of file!
report_fatal_error("Section header table goes past end of file!"); EC = object_error::parse_failed;
return;
}
// The getNumSections() call below depends on SectionHeaderTable being set. // The getNumSections() call below depends on SectionHeaderTable being set.
SectionHeaderTable = SectionHeaderTable =
reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset); reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
const uint64_t SectionTableSize = getNumSections() * Header->e_shentsize; const uint64_t SectionTableSize = getNumSections() * Header->e_shentsize;
if (SectionTableOffset + SectionTableSize > FileSize) if (SectionTableOffset + SectionTableSize > FileSize) {
// FIXME: Proper error handling. // Section table goes past end of file!
report_fatal_error("Section table goes past end of file!"); EC = object_error::parse_failed;
return;
}
// Scan sections for special sections. // Scan sections for special sections.
for (const Elf_Shdr &Sec : sections()) { for (const Elf_Shdr &Sec : sections()) {
switch (Sec.sh_type) { switch (Sec.sh_type) {
case ELF::SHT_SYMTAB_SHNDX: case ELF::SHT_SYMTAB_SHNDX:
if (SymbolTableSectionHeaderIndex) if (SymbolTableSectionHeaderIndex) {
// FIXME: Proper error handling. // More than one .symtab_shndx!
report_fatal_error("More than one .symtab_shndx!"); EC = object_error::parse_failed;
return;
}
SymbolTableSectionHeaderIndex = &Sec; SymbolTableSectionHeaderIndex = &Sec;
break; break;
case ELF::SHT_SYMTAB: case ELF::SHT_SYMTAB:
if (dot_symtab_sec) if (dot_symtab_sec) {
// FIXME: Proper error handling. // More than one .symtab!
report_fatal_error("More than one .symtab!"); EC = object_error::parse_failed;
return;
}
dot_symtab_sec = &Sec; dot_symtab_sec = &Sec;
dot_strtab_sec = getSection(Sec.sh_link); dot_strtab_sec = getSection(Sec.sh_link);
break; break;
case ELF::SHT_DYNSYM: { case ELF::SHT_DYNSYM: {
if (DynSymRegion.Addr) if (DynSymRegion.Addr) {
// FIXME: Proper error handling. // More than one .dynsym!
report_fatal_error("More than one .dynsym!"); EC = object_error::parse_failed;
return;
}
DynSymRegion.Addr = base() + Sec.sh_offset; DynSymRegion.Addr = base() + Sec.sh_offset;
DynSymRegion.Size = Sec.sh_size; DynSymRegion.Size = Sec.sh_size;
DynSymRegion.EntSize = Sec.sh_entsize; DynSymRegion.EntSize = Sec.sh_entsize;
@ -685,29 +695,37 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &ec)
break; break;
} }
case ELF::SHT_DYNAMIC: case ELF::SHT_DYNAMIC:
if (DynamicRegion.Addr) if (DynamicRegion.Addr) {
// FIXME: Proper error handling. // More than one .dynamic!
report_fatal_error("More than one .dynamic!"); EC = object_error::parse_failed;
return;
}
DynamicRegion.Addr = base() + Sec.sh_offset; DynamicRegion.Addr = base() + Sec.sh_offset;
DynamicRegion.Size = Sec.sh_size; DynamicRegion.Size = Sec.sh_size;
DynamicRegion.EntSize = Sec.sh_entsize; DynamicRegion.EntSize = Sec.sh_entsize;
break; break;
case ELF::SHT_GNU_versym: case ELF::SHT_GNU_versym:
if (dot_gnu_version_sec != nullptr) if (dot_gnu_version_sec != nullptr) {
// FIXME: Proper error handling. // More than one .gnu.version section!
report_fatal_error("More than one .gnu.version section!"); EC = object_error::parse_failed;
return;
}
dot_gnu_version_sec = &Sec; dot_gnu_version_sec = &Sec;
break; break;
case ELF::SHT_GNU_verdef: case ELF::SHT_GNU_verdef:
if (dot_gnu_version_d_sec != nullptr) if (dot_gnu_version_d_sec != nullptr) {
// FIXME: Proper error handling. // More than one .gnu.version_d section!
report_fatal_error("More than one .gnu.version_d section!"); EC = object_error::parse_failed;
return;
}
dot_gnu_version_d_sec = &Sec; dot_gnu_version_d_sec = &Sec;
break; break;
case ELF::SHT_GNU_verneed: case ELF::SHT_GNU_verneed:
if (dot_gnu_version_r_sec != nullptr) if (dot_gnu_version_r_sec != nullptr) {
// FIXME: Proper error handling. // More than one .gnu.version_r section!
report_fatal_error("More than one .gnu.version_r section!"); EC = object_error::parse_failed;
return;
}
dot_gnu_version_r_sec = &Sec; dot_gnu_version_r_sec = &Sec;
break; break;
} }
@ -744,7 +762,7 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &ec)
} }
} }
ec = std::error_code(); EC = std::error_code();
} }
// Get the symbol table index in the symtab section given a symbol // Get the symbol table index in the symtab section given a symbol
@ -898,11 +916,8 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(Elf_Sym_Iter Sym) const {
template <class ELFT> template <class ELFT>
ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Shdr *Section, ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Shdr *Section,
const Elf_Sym *Symb) const { const Elf_Sym *Symb) const {
if (Symb->st_name == 0) { if (Symb->st_name == 0)
const Elf_Shdr *ContainingSec = getSection(Symb); return StringRef("");
if (ContainingSec)
return getSectionName(ContainingSec);
}
const Elf_Shdr *StrTab = getSection(Section->sh_link); const Elf_Shdr *StrTab = getSection(Section->sh_link);
if (Symb->st_name >= StrTab->sh_size) if (Symb->st_name >= StrTab->sh_size)

View File

@ -79,9 +79,8 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
StringRef &Res) const override; StringRef &Res) const override;
std::error_code getSymbolAddress(DataRefImpl Symb, std::error_code getSymbolAddress(DataRefImpl Symb,
uint64_t &Res) const override; uint64_t &Res) const override;
std::error_code getSymbolAlignment(DataRefImpl Symb, uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint32_t &Res) const override; uint64_t getSymbolSize(DataRefImpl Symb) const override;
std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override;
std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override; std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override;
std::error_code getSymbolType(DataRefImpl Symb, std::error_code getSymbolType(DataRefImpl Symb,
@ -119,9 +118,6 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
std::error_code std::error_code
getRelocationTypeName(DataRefImpl Rel, getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const override; SmallVectorImpl<char> &Result) const override;
std::error_code
getRelocationValueString(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const override;
uint64_t getROffset(DataRefImpl Rel) const; uint64_t getROffset(DataRefImpl Rel) const;
StringRef getRelocationTypeName(uint32_t Type) const; StringRef getRelocationTypeName(uint32_t Type) const;
@ -227,7 +223,7 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
std::error_code getPlatformFlags(unsigned &Result) const override { std::error_code getPlatformFlags(unsigned &Result) const override {
Result = EF.getHeader()->e_flags; Result = EF.getHeader()->e_flags;
return object_error::success; return std::error_code();
} }
const ELFFile<ELFT> *getELFFile() const { return &EF; } const ELFFile<ELFT> *getELFFile() const { return &EF; }
@ -244,12 +240,10 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
bool isRelocatableObject() const override; bool isRelocatableObject() const override;
}; };
// Use an alignment of 2 for the typedefs since that is the worst case for typedef ELFObjectFile<ELFType<support::little, false>> ELF32LEObjectFile;
// ELF files in archives. typedef ELFObjectFile<ELFType<support::little, true>> ELF64LEObjectFile;
typedef ELFObjectFile<ELFType<support::little, 2, false> > ELF32LEObjectFile; typedef ELFObjectFile<ELFType<support::big, false>> ELF32BEObjectFile;
typedef ELFObjectFile<ELFType<support::little, 2, true> > ELF64LEObjectFile; typedef ELFObjectFile<ELFType<support::big, true>> ELF64BEObjectFile;
typedef ELFObjectFile<ELFType<support::big, 2, false> > ELF32BEObjectFile;
typedef ELFObjectFile<ELFType<support::big, 2, true> > ELF64BEObjectFile;
template <class ELFT> template <class ELFT>
void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Symb) const { void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Symb) const {
@ -263,7 +257,7 @@ std::error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb,
if (!Name) if (!Name)
return Name.getError(); return Name.getError();
Result = *Name; Result = *Name;
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -277,7 +271,7 @@ std::error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef,
if (!Ver) if (!Ver)
return Ver.getError(); return Ver.getError();
Version = *Ver; Version = *Ver;
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -300,10 +294,10 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
case ELF::SHN_COMMON: case ELF::SHN_COMMON:
case ELF::SHN_UNDEF: case ELF::SHN_UNDEF:
Result = UnknownAddressOrSize; Result = UnknownAddressOrSize;
return object_error::success; return std::error_code();
case ELF::SHN_ABS: case ELF::SHN_ABS:
Result = ESym->st_value; Result = ESym->st_value;
return object_error::success; return std::error_code();
default: default:
break; break;
} }
@ -322,32 +316,27 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
Result += Section->sh_addr; Result += Section->sh_addr;
} }
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
std::error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb, uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const {
uint32_t &Res) const {
Elf_Sym_Iter Sym = toELFSymIter(Symb); Elf_Sym_Iter Sym = toELFSymIter(Symb);
if (Sym->st_shndx == ELF::SHN_COMMON) if (Sym->st_shndx == ELF::SHN_COMMON)
Res = Sym->st_value; return Sym->st_value;
else return 0;
Res = 0;
return object_error::success;
} }
template <class ELFT> template <class ELFT>
std::error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb, uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb) const {
uint64_t &Result) const { return toELFSymIter(Symb)->st_size;
Result = toELFSymIter(Symb)->st_size;
return object_error::success;
} }
template <class ELFT> template <class ELFT>
std::error_code ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb, std::error_code ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb,
uint8_t &Result) const { uint8_t &Result) const {
Result = toELFSymIter(Symb)->st_other; Result = toELFSymIter(Symb)->st_other;
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -378,7 +367,7 @@ ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb,
Result = SymbolRef::ST_Other; Result = SymbolRef::ST_Other;
break; break;
} }
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -435,7 +424,7 @@ std::error_code
ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
section_iterator &Res) const { section_iterator &Res) const {
Res = getSymbolSection(getSymbol(Symb)); Res = getSymbolSection(getSymbol(Symb));
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -450,7 +439,7 @@ std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec,
if (!Name) if (!Name)
return Name.getError(); return Name.getError();
Result = *Name; Result = *Name;
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -469,7 +458,7 @@ ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec,
StringRef &Result) const { StringRef &Result) const {
Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size);
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -624,7 +613,7 @@ ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel,
Result = ROffset; Result = ROffset;
} }
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -634,7 +623,7 @@ ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel,
assert(EF.getHeader()->e_type == ELF::ET_REL && assert(EF.getHeader()->e_type == ELF::ET_REL &&
"Only relocatable object files have relocation offsets"); "Only relocatable object files have relocation offsets");
Result = getROffset(Rel); Result = getROffset(Rel);
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -666,7 +655,7 @@ std::error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel,
break; break;
} }
} }
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -693,7 +682,7 @@ std::error_code ELFObjectFile<ELFT>::getRelocationTypeName(
} }
EF.getRelocationTypeName(type, Result); EF.getRelocationTypeName(type, Result);
return object_error::success; return std::error_code();
} }
template <class ELFT> template <class ELFT>
@ -706,96 +695,15 @@ ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel,
report_fatal_error("Invalid section type in Rel!"); report_fatal_error("Invalid section type in Rel!");
case ELF::SHT_REL: { case ELF::SHT_REL: {
Result = 0; Result = 0;
return object_error::success; return std::error_code();
} }
case ELF::SHT_RELA: { case ELF::SHT_RELA: {
Result = getRela(Rel)->r_addend; Result = getRela(Rel)->r_addend;
return object_error::success; return std::error_code();
} }
} }
} }
template <class ELFT>
std::error_code ELFObjectFile<ELFT>::getRelocationValueString(
DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
const Elf_Shdr *sec = getRelSection(Rel);
uint8_t type;
StringRef res;
int64_t addend = 0;
uint16_t symbol_index = 0;
switch (sec->sh_type) {
default:
return object_error::parse_failed;
case ELF::SHT_REL: {
type = getRel(Rel)->getType(EF.isMips64EL());
symbol_index = getRel(Rel)->getSymbol(EF.isMips64EL());
// TODO: Read implicit addend from section data.
break;
}
case ELF::SHT_RELA: {
type = getRela(Rel)->getType(EF.isMips64EL());
symbol_index = getRela(Rel)->getSymbol(EF.isMips64EL());
addend = getRela(Rel)->r_addend;
break;
}
}
const Elf_Sym *symb =
EF.template getEntry<Elf_Sym>(sec->sh_link, symbol_index);
ErrorOr<StringRef> SymName =
EF.getSymbolName(EF.getSection(sec->sh_link), symb);
if (!SymName)
return SymName.getError();
switch (EF.getHeader()->e_machine) {
case ELF::EM_X86_64:
switch (type) {
case ELF::R_X86_64_PC8:
case ELF::R_X86_64_PC16:
case ELF::R_X86_64_PC32: {
std::string fmtbuf;
raw_string_ostream fmt(fmtbuf);
fmt << *SymName << (addend < 0 ? "" : "+") << addend << "-P";
fmt.flush();
Result.append(fmtbuf.begin(), fmtbuf.end());
} break;
case ELF::R_X86_64_8:
case ELF::R_X86_64_16:
case ELF::R_X86_64_32:
case ELF::R_X86_64_32S:
case ELF::R_X86_64_64: {
std::string fmtbuf;
raw_string_ostream fmt(fmtbuf);
fmt << *SymName << (addend < 0 ? "" : "+") << addend;
fmt.flush();
Result.append(fmtbuf.begin(), fmtbuf.end());
} break;
default:
res = "Unknown";
}
break;
case ELF::EM_AARCH64: {
std::string fmtbuf;
raw_string_ostream fmt(fmtbuf);
fmt << *SymName;
if (addend != 0)
fmt << (addend < 0 ? "" : "+") << addend;
fmt.flush();
Result.append(fmtbuf.begin(), fmtbuf.end());
break;
}
case ELF::EM_386:
case ELF::EM_ARM:
case ELF::EM_HEXAGON:
case ELF::EM_MIPS:
res = *SymName;
break;
default:
res = "Unknown";
}
if (Result.empty())
Result.append(res.begin(), res.end());
return object_error::success;
}
template <class ELFT> template <class ELFT>
const typename ELFFile<ELFT>::Elf_Sym * const typename ELFFile<ELFT>::Elf_Sym *
ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const { ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const {

View File

@ -10,7 +10,6 @@
#ifndef LLVM_OBJECT_ELFTYPES_H #ifndef LLVM_OBJECT_ELFTYPES_H
#define LLVM_OBJECT_ELFTYPES_H #define LLVM_OBJECT_ELFTYPES_H
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "llvm/Support/ELF.h" #include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
@ -20,95 +19,74 @@ namespace object {
using support::endianness; using support::endianness;
template <endianness target_endianness, std::size_t max_alignment, template <endianness target_endianness, bool is64Bits> struct ELFType {
bool is64Bits>
struct ELFType {
static const endianness TargetEndianness = target_endianness; static const endianness TargetEndianness = target_endianness;
static const std::size_t MaxAlignment = max_alignment;
static const bool Is64Bits = is64Bits; static const bool Is64Bits = is64Bits;
}; };
template <typename T, int max_align> struct MaximumAlignment { // Use an alignment of 2 for the typedefs since that is the worst case for
enum { value = AlignOf<T>::Alignment > max_align ? max_align // ELF files in archives.
: AlignOf<T>::Alignment
};
};
// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. // Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
template <endianness target_endianness, std::size_t max_alignment> template <endianness target_endianness> struct ELFDataTypeTypedefHelperCommon {
struct ELFDataTypeTypedefHelperCommon {
typedef support::detail::packed_endian_specific_integral< typedef support::detail::packed_endian_specific_integral<
uint16_t, target_endianness, uint16_t, target_endianness, 2> Elf_Half;
MaximumAlignment<uint16_t, max_alignment>::value> Elf_Half;
typedef support::detail::packed_endian_specific_integral< typedef support::detail::packed_endian_specific_integral<
uint32_t, target_endianness, uint32_t, target_endianness, 2> Elf_Word;
MaximumAlignment<uint32_t, max_alignment>::value> Elf_Word;
typedef support::detail::packed_endian_specific_integral< typedef support::detail::packed_endian_specific_integral<
int32_t, target_endianness, int32_t, target_endianness, 2> Elf_Sword;
MaximumAlignment<int32_t, max_alignment>::value> Elf_Sword;
typedef support::detail::packed_endian_specific_integral< typedef support::detail::packed_endian_specific_integral<
uint64_t, target_endianness, uint64_t, target_endianness, 2> Elf_Xword;
MaximumAlignment<uint64_t, max_alignment>::value> Elf_Xword;
typedef support::detail::packed_endian_specific_integral< typedef support::detail::packed_endian_specific_integral<
int64_t, target_endianness, int64_t, target_endianness, 2> Elf_Sxword;
MaximumAlignment<int64_t, max_alignment>::value> Elf_Sxword;
}; };
template <class ELFT> struct ELFDataTypeTypedefHelper; template <class ELFT> struct ELFDataTypeTypedefHelper;
/// ELF 32bit types. /// ELF 32bit types.
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, false> > struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, false>>
: ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { : ELFDataTypeTypedefHelperCommon<TargetEndianness> {
typedef uint32_t value_type; typedef uint32_t value_type;
typedef support::detail::packed_endian_specific_integral< typedef support::detail::packed_endian_specific_integral<
value_type, TargetEndianness, value_type, TargetEndianness, 2> Elf_Addr;
MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr;
typedef support::detail::packed_endian_specific_integral< typedef support::detail::packed_endian_specific_integral<
value_type, TargetEndianness, value_type, TargetEndianness, 2> Elf_Off;
MaximumAlignment<value_type, MaxAlign>::value> Elf_Off;
}; };
/// ELF 64bit types. /// ELF 64bit types.
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, true> > struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>>
: ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { : ELFDataTypeTypedefHelperCommon<TargetEndianness> {
typedef uint64_t value_type; typedef uint64_t value_type;
typedef support::detail::packed_endian_specific_integral< typedef support::detail::packed_endian_specific_integral<
value_type, TargetEndianness, value_type, TargetEndianness, 2> Elf_Addr;
MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr;
typedef support::detail::packed_endian_specific_integral< typedef support::detail::packed_endian_specific_integral<
value_type, TargetEndianness, value_type, TargetEndianness, 2> Elf_Off;
MaximumAlignment<value_type, MaxAlign>::value> Elf_Off;
}; };
// I really don't like doing this, but the alternative is copypasta. // I really don't like doing this, but the alternative is copypasta.
#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ #define LLVM_ELF_IMPORT_TYPES(E, W) \
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Addr \ typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Addr Elf_Addr; \
Elf_Addr; \ typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Off Elf_Off; \
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Off \ typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Half Elf_Half; \
Elf_Off; \ typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Word Elf_Word; \
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Half \ typedef \
Elf_Half; \ typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Sword Elf_Sword; \
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Word \ typedef \
Elf_Word; \ typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Xword Elf_Xword; \
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Sword \ typedef \
Elf_Sword; \ typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Sxword Elf_Sxword;
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Xword \
Elf_Xword; \
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Sxword \
Elf_Sxword;
#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ #define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \
LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::Is64Bits)
ELFT::Is64Bits)
// Section header. // Section header.
template <class ELFT> struct Elf_Shdr_Base; template <class ELFT> struct Elf_Shdr_Base;
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, false> > { struct Elf_Shdr_Base<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_name; // Section name (index into string table)
Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_type; // Section type (SHT_*)
Elf_Word sh_flags; // Section flags (SHF_*) Elf_Word sh_flags; // Section flags (SHF_*)
@ -121,9 +99,9 @@ struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, false> > {
Elf_Word sh_entsize; // Size of records contained within the section Elf_Word sh_entsize; // Size of records contained within the section
}; };
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, true> > { struct Elf_Shdr_Base<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_name; // Section name (index into string table)
Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_type; // Section type (SHT_*)
Elf_Xword sh_flags; // Section flags (SHF_*) Elf_Xword sh_flags; // Section flags (SHF_*)
@ -151,9 +129,9 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> {
template <class ELFT> struct Elf_Sym_Base; template <class ELFT> struct Elf_Sym_Base;
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, false> > { struct Elf_Sym_Base<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word st_name; // Symbol name (index into string table) Elf_Word st_name; // Symbol name (index into string table)
Elf_Addr st_value; // Value or address associated with the symbol Elf_Addr st_value; // Value or address associated with the symbol
Elf_Word st_size; // Size of the symbol Elf_Word st_size; // Size of the symbol
@ -162,9 +140,9 @@ struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, false> > {
Elf_Half st_shndx; // Which section (header table index) it's defined in Elf_Half st_shndx; // Which section (header table index) it's defined in
}; };
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > { struct Elf_Sym_Base<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word st_name; // Symbol name (index into string table) Elf_Word st_name; // Symbol name (index into string table)
unsigned char st_info; // Symbol's type and binding attributes unsigned char st_info; // Symbol's type and binding attributes
unsigned char st_other; // Must be zero; reserved unsigned char st_other; // Must be zero; reserved
@ -176,6 +154,7 @@ struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > {
template <class ELFT> template <class ELFT>
struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
using Elf_Sym_Base<ELFT>::st_info; using Elf_Sym_Base<ELFT>::st_info;
using Elf_Sym_Base<ELFT>::st_shndx;
using Elf_Sym_Base<ELFT>::st_other; using Elf_Sym_Base<ELFT>::st_other;
// These accessors and mutators correspond to the ELF32_ST_BIND, // These accessors and mutators correspond to the ELF32_ST_BIND,
@ -198,6 +177,25 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
assert(v < 4 && "Invalid value for visibility"); assert(v < 4 && "Invalid value for visibility");
st_other = (st_other & ~0x3) | v; st_other = (st_other & ~0x3) | v;
} }
bool isAbsolute() const { return st_shndx == ELF::SHN_ABS; }
bool isCommon() const {
return getType() == ELF::STT_COMMON || st_shndx == ELF::SHN_COMMON;
}
bool isDefined() const {
return !isUndefined() &&
!(st_shndx >= ELF::SHN_LORESERVE && st_shndx < ELF::SHN_ABS);
}
bool isProcessorSpecific() const {
return st_shndx >= ELF::SHN_LOPROC && st_shndx <= ELF::SHN_HIPROC;
}
bool isOSSpecific() const {
return st_shndx >= ELF::SHN_LOOS && st_shndx <= ELF::SHN_HIOS;
}
bool isReserved() const {
return st_shndx > ELF::SHN_HIOS && st_shndx < ELF::SHN_ABS;
}
bool isUndefined() const { return st_shndx == ELF::SHN_UNDEF; }
}; };
/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section
@ -267,9 +265,9 @@ struct Elf_Vernaux_Impl {
/// table section (.dynamic) look like. /// table section (.dynamic) look like.
template <class ELFT> struct Elf_Dyn_Base; template <class ELFT> struct Elf_Dyn_Base;
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, false> > { struct Elf_Dyn_Base<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Sword d_tag; Elf_Sword d_tag;
union { union {
Elf_Word d_val; Elf_Word d_val;
@ -277,9 +275,9 @@ struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, false> > {
} d_un; } d_un;
}; };
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, true> > { struct Elf_Dyn_Base<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Sxword d_tag; Elf_Sxword d_tag;
union { union {
Elf_Xword d_val; Elf_Xword d_val;
@ -300,9 +298,9 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
// Elf_Rel: Elf Relocation // Elf_Rel: Elf Relocation
template <class ELFT, bool isRela> struct Elf_Rel_Base; template <class ELFT, bool isRela> struct Elf_Rel_Base;
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> { struct Elf_Rel_Base<ELFType<TargetEndianness, false>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
Elf_Word r_info; // Symbol table index and type of relocation to apply Elf_Word r_info; // Symbol table index and type of relocation to apply
@ -316,9 +314,9 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> {
} }
}; };
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> { struct Elf_Rel_Base<ELFType<TargetEndianness, true>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
Elf_Xword r_info; // Symbol table index and type of relocation to apply Elf_Xword r_info; // Symbol table index and type of relocation to apply
@ -341,9 +339,9 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> {
} }
}; };
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> { struct Elf_Rel_Base<ELFType<TargetEndianness, false>, true> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
Elf_Word r_info; // Symbol table index and type of relocation to apply Elf_Word r_info; // Symbol table index and type of relocation to apply
Elf_Sword r_addend; // Compute value for relocatable field by adding this Elf_Sword r_addend; // Compute value for relocatable field by adding this
@ -358,9 +356,9 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> {
} }
}; };
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> { struct Elf_Rel_Base<ELFType<TargetEndianness, true>, true> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
Elf_Xword r_info; // Symbol table index and type of relocation to apply Elf_Xword r_info; // Symbol table index and type of relocation to apply
Elf_Sxword r_addend; // Compute value for relocatable field by adding this. Elf_Sxword r_addend; // Compute value for relocatable field by adding this.
@ -386,11 +384,10 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> {
template <class ELFT, bool isRela> struct Elf_Rel_Impl; template <class ELFT, bool isRela> struct Elf_Rel_Impl;
template <endianness TargetEndianness, std::size_t MaxAlign, bool isRela> template <endianness TargetEndianness, bool isRela>
struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>, struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, isRela>
isRela> : Elf_Rel_Base< : Elf_Rel_Base<ELFType<TargetEndianness, true>, isRela> {
ELFType<TargetEndianness, MaxAlign, true>, isRela> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
// These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
// and ELF64_R_INFO macros defined in the ELF specification: // and ELF64_R_INFO macros defined in the ELF specification:
@ -411,11 +408,10 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>,
} }
}; };
template <endianness TargetEndianness, std::size_t MaxAlign, bool isRela> template <endianness TargetEndianness, bool isRela>
struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, false>, struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, isRela>
isRela> : Elf_Rel_Base< : Elf_Rel_Base<ELFType<TargetEndianness, false>, isRela> {
ELFType<TargetEndianness, MaxAlign, false>, isRela> { LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
// These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
// and ELF32_R_INFO macros defined in the ELF specification: // and ELF32_R_INFO macros defined in the ELF specification:
@ -463,9 +459,9 @@ struct Elf_Ehdr_Impl {
template <class ELFT> struct Elf_Phdr_Impl; template <class ELFT> struct Elf_Phdr_Impl;
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, false> > { struct Elf_Phdr_Impl<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word p_type; // Type of segment Elf_Word p_type; // Type of segment
Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Off p_offset; // FileOffset where segment is located, in bytes
Elf_Addr p_vaddr; // Virtual Address of beginning of segment Elf_Addr p_vaddr; // Virtual Address of beginning of segment
@ -476,9 +472,9 @@ struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, false> > {
Elf_Word p_align; // Segment alignment constraint Elf_Word p_align; // Segment alignment constraint
}; };
template <endianness TargetEndianness, std::size_t MaxAlign> template <endianness TargetEndianness>
struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > { struct Elf_Phdr_Impl<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word p_type; // Type of segment Elf_Word p_type; // Type of segment
Elf_Word p_flags; // Segment flags Elf_Word p_flags; // Segment flags
Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Off p_offset; // FileOffset where segment is located, in bytes
@ -493,17 +489,17 @@ struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > {
template <class ELFT> template <class ELFT>
struct Elf_Mips_RegInfo; struct Elf_Mips_RegInfo;
template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign> template <llvm::support::endianness TargetEndianness>
struct Elf_Mips_RegInfo<ELFType<TargetEndianness, MaxAlign, false>> { struct Elf_Mips_RegInfo<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word ri_gprmask; // bit-mask of used general registers Elf_Word ri_gprmask; // bit-mask of used general registers
Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
Elf_Addr ri_gp_value; // gp register value Elf_Addr ri_gp_value; // gp register value
}; };
template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign> template <llvm::support::endianness TargetEndianness>
struct Elf_Mips_RegInfo<ELFType<TargetEndianness, MaxAlign, true>> { struct Elf_Mips_RegInfo<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word ri_gprmask; // bit-mask of used general registers Elf_Word ri_gprmask; // bit-mask of used general registers
Elf_Word ri_pad; // unused padding field Elf_Word ri_pad; // unused padding field
Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers

View File

@ -22,12 +22,15 @@ namespace object {
const std::error_category &object_category(); const std::error_category &object_category();
enum class object_error { enum class object_error {
success = 0, // Error code 0 is absent. Use std::error_code() instead.
arch_not_found, arch_not_found = 1,
invalid_file_type, invalid_file_type,
parse_failed, parse_failed,
unexpected_eof, unexpected_eof,
bitcode_section_not_found, bitcode_section_not_found,
macho_small_load_command,
macho_load_segment_too_many_sections,
macho_load_segment_too_small,
}; };
inline std::error_code make_error_code(object_error e) { inline std::error_code make_error_code(object_error e) {

View File

@ -190,6 +190,8 @@ class MachOObjectFile : public ObjectFile {
const char *Ptr; // Where in memory the load command is. const char *Ptr; // Where in memory the load command is.
MachO::load_command C; // The command itself. MachO::load_command C; // The command itself.
}; };
typedef SmallVector<LoadCommandInfo, 4> LoadCommandList;
typedef LoadCommandList::const_iterator load_command_iterator;
MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
std::error_code &EC); std::error_code &EC);
@ -204,9 +206,8 @@ class MachOObjectFile : public ObjectFile {
std::error_code getSymbolAddress(DataRefImpl Symb, std::error_code getSymbolAddress(DataRefImpl Symb,
uint64_t &Res) const override; uint64_t &Res) const override;
std::error_code getSymbolAlignment(DataRefImpl Symb, uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint32_t &Res) const override; uint64_t getSymbolSize(DataRefImpl Symb) const override;
std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override;
std::error_code getSymbolType(DataRefImpl Symb, std::error_code getSymbolType(DataRefImpl Symb,
SymbolRef::Type &Res) const override; SymbolRef::Type &Res) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override;
@ -241,11 +242,9 @@ class MachOObjectFile : public ObjectFile {
std::error_code std::error_code
getRelocationTypeName(DataRefImpl Rel, getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const override; SmallVectorImpl<char> &Result) const override;
std::error_code
getRelocationValueString(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const override;
std::error_code getRelocationHidden(DataRefImpl Rel, std::error_code getRelocationHidden(DataRefImpl Rel,
bool &Result) const override; bool &Result) const override;
uint8_t getRelocationLength(DataRefImpl Rel) const;
// MachO specific. // MachO specific.
std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const; std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const;
@ -273,10 +272,14 @@ class MachOObjectFile : public ObjectFile {
dice_iterator begin_dices() const; dice_iterator begin_dices() const;
dice_iterator end_dices() const; dice_iterator end_dices() const;
load_command_iterator begin_load_commands() const;
load_command_iterator end_load_commands() const;
iterator_range<load_command_iterator> load_commands() const;
/// For use iterating over all exported symbols. /// For use iterating over all exported symbols.
iterator_range<export_iterator> exports() const; iterator_range<export_iterator> exports() const;
/// For use examining a trie not in a MachOObjectFile. /// For use examining a trie not in a MachOObjectFile.
static iterator_range<export_iterator> exports(ArrayRef<uint8_t> Trie); static iterator_range<export_iterator> exports(ArrayRef<uint8_t> Trie);
@ -329,10 +332,6 @@ class MachOObjectFile : public ObjectFile {
unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const;
SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const; SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const;
// Walk load commands.
LoadCommandInfo getFirstLoadCommandInfo() const;
LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const;
// MachO specific structures. // MachO specific structures.
MachO::section getSection(DataRefImpl DRI) const; MachO::section getSection(DataRefImpl DRI) const;
MachO::section_64 getSection64(DataRefImpl DRI) const; MachO::section_64 getSection64(DataRefImpl DRI) const;
@ -386,8 +385,8 @@ class MachOObjectFile : public ObjectFile {
MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; MachO::any_relocation_info getRelocation(DataRefImpl Rel) const;
MachO::data_in_code_entry getDice(DataRefImpl Rel) const; MachO::data_in_code_entry getDice(DataRefImpl Rel) const;
MachO::mach_header getHeader() const; const MachO::mach_header &getHeader() const;
MachO::mach_header_64 getHeader64() const; const MachO::mach_header_64 &getHeader64() const;
uint32_t uint32_t
getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC, getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC,
unsigned Index) const; unsigned Index) const;
@ -430,10 +429,15 @@ class MachOObjectFile : public ObjectFile {
} }
private: private:
union {
MachO::mach_header_64 Header64;
MachO::mach_header Header;
};
typedef SmallVector<const char*, 1> SectionList; typedef SmallVector<const char*, 1> SectionList;
SectionList Sections; SectionList Sections;
typedef SmallVector<const char*, 1> LibraryList; typedef SmallVector<const char*, 1> LibraryList;
LibraryList Libraries; LibraryList Libraries;
LoadCommandList LoadCommands;
typedef SmallVector<StringRef, 1> LibraryShortName; typedef SmallVector<StringRef, 1> LibraryShortName;
mutable LibraryShortName LibrariesShortNames; mutable LibraryShortName LibrariesShortNames;
const char *SymtabLoadCmd; const char *SymtabLoadCmd;
@ -472,7 +476,7 @@ inline std::error_code DiceRef::getOffset(uint32_t &Result) const {
static_cast<const MachOObjectFile *>(OwningObject); static_cast<const MachOObjectFile *>(OwningObject);
MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
Result = Dice.offset; Result = Dice.offset;
return object_error::success; return std::error_code();
} }
inline std::error_code DiceRef::getLength(uint16_t &Result) const { inline std::error_code DiceRef::getLength(uint16_t &Result) const {
@ -480,7 +484,7 @@ inline std::error_code DiceRef::getLength(uint16_t &Result) const {
static_cast<const MachOObjectFile *>(OwningObject); static_cast<const MachOObjectFile *>(OwningObject);
MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
Result = Dice.length; Result = Dice.length;
return object_error::success; return std::error_code();
} }
inline std::error_code DiceRef::getKind(uint16_t &Result) const { inline std::error_code DiceRef::getKind(uint16_t &Result) const {
@ -488,7 +492,7 @@ inline std::error_code DiceRef::getKind(uint16_t &Result) const {
static_cast<const MachOObjectFile *>(OwningObject); static_cast<const MachOObjectFile *>(OwningObject);
MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
Result = Dice.kind; Result = Dice.kind;
return object_error::success; return std::error_code();
} }
inline DataRefImpl DiceRef::getRawDataRefImpl() const { inline DataRefImpl DiceRef::getRawDataRefImpl() const {

View File

@ -66,11 +66,6 @@ class RelocationRef {
/// This is for display purposes only. /// This is for display purposes only.
std::error_code getTypeName(SmallVectorImpl<char> &Result) const; std::error_code getTypeName(SmallVectorImpl<char> &Result) const;
/// @brief Get a string that represents the calculation of the value of this
/// relocation.
///
/// This is for display purposes only.
std::error_code getValueString(SmallVectorImpl<char> &Result) const;
DataRefImpl getRawDataRefImpl() const; DataRefImpl getRawDataRefImpl() const;
const ObjectFile *getObjectFile() const; const ObjectFile *getObjectFile() const;
@ -146,8 +141,8 @@ class SymbolRef : public BasicSymbolRef {
/// mapped). /// mapped).
std::error_code getAddress(uint64_t &Result) const; std::error_code getAddress(uint64_t &Result) const;
/// @brief Get the alignment of this symbol as the actual value (not log 2). /// @brief Get the alignment of this symbol as the actual value (not log 2).
std::error_code getAlignment(uint32_t &Result) const; uint32_t getAlignment() const;
std::error_code getSize(uint64_t &Result) const; uint64_t getSize() const;
std::error_code getType(SymbolRef::Type &Result) const; std::error_code getType(SymbolRef::Type &Result) const;
std::error_code getOther(uint8_t &Result) const; std::error_code getOther(uint8_t &Result) const;
@ -206,10 +201,8 @@ class ObjectFile : public SymbolicFile {
DataRefImpl Symb) const override; DataRefImpl Symb) const override;
virtual std::error_code getSymbolAddress(DataRefImpl Symb, virtual std::error_code getSymbolAddress(DataRefImpl Symb,
uint64_t &Res) const = 0; uint64_t &Res) const = 0;
virtual std::error_code getSymbolAlignment(DataRefImpl Symb, virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const;
uint32_t &Res) const; virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0;
virtual std::error_code getSymbolSize(DataRefImpl Symb,
uint64_t &Res) const = 0;
virtual std::error_code getSymbolType(DataRefImpl Symb, virtual std::error_code getSymbolType(DataRefImpl Symb,
SymbolRef::Type &Res) const = 0; SymbolRef::Type &Res) const = 0;
virtual std::error_code getSymbolSection(DataRefImpl Symb, virtual std::error_code getSymbolSection(DataRefImpl Symb,
@ -254,13 +247,10 @@ class ObjectFile : public SymbolicFile {
virtual std::error_code virtual std::error_code
getRelocationTypeName(DataRefImpl Rel, getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const = 0; SmallVectorImpl<char> &Result) const = 0;
virtual std::error_code
getRelocationValueString(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const = 0;
virtual std::error_code getRelocationHidden(DataRefImpl Rel, virtual std::error_code getRelocationHidden(DataRefImpl Rel,
bool &Result) const { bool &Result) const {
Result = false; Result = false;
return object_error::success; return std::error_code();
} }
public: public:
@ -334,12 +324,12 @@ inline std::error_code SymbolRef::getAddress(uint64_t &Result) const {
return getObject()->getSymbolAddress(getRawDataRefImpl(), Result); return getObject()->getSymbolAddress(getRawDataRefImpl(), Result);
} }
inline std::error_code SymbolRef::getAlignment(uint32_t &Result) const { inline uint32_t SymbolRef::getAlignment() const {
return getObject()->getSymbolAlignment(getRawDataRefImpl(), Result); return getObject()->getSymbolAlignment(getRawDataRefImpl());
} }
inline std::error_code SymbolRef::getSize(uint64_t &Result) const { inline uint64_t SymbolRef::getSize() const {
return getObject()->getSymbolSize(getRawDataRefImpl(), Result); return getObject()->getSymbolSize(getRawDataRefImpl());
} }
inline std::error_code SymbolRef::getSection(section_iterator &Result) const { inline std::error_code SymbolRef::getSection(section_iterator &Result) const {
@ -482,11 +472,6 @@ RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const {
return OwningObject->getRelocationTypeName(RelocationPimpl, Result); return OwningObject->getRelocationTypeName(RelocationPimpl, Result);
} }
inline std::error_code
RelocationRef::getValueString(SmallVectorImpl<char> &Result) const {
return OwningObject->getRelocationValueString(RelocationPimpl, Result);
}
inline std::error_code RelocationRef::getHidden(bool &Result) const { inline std::error_code RelocationRef::getHidden(bool &Result) const {
return OwningObject->getRelocationHidden(RelocationPimpl, Result); return OwningObject->getRelocationHidden(RelocationPimpl, Result);
} }

View File

@ -19,9 +19,11 @@
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Object/COFF.h" #include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ELF.h" #include "llvm/Support/ELF.h"
#include "llvm/Support/MachO.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
namespace llvm { namespace llvm {
@ -52,6 +54,8 @@ class RelocVisitor {
return visitELF(RelocType, R, Value); return visitELF(RelocType, R, Value);
if (isa<COFFObjectFile>(ObjToVisit)) if (isa<COFFObjectFile>(ObjToVisit))
return visitCOFF(RelocType, R, Value); return visitCOFF(RelocType, R, Value);
if (isa<MachOObjectFile>(ObjToVisit))
return visitMachO(RelocType, R, Value);
HasError = true; HasError = true;
return RelocToApply(); return RelocToApply();
@ -221,6 +225,20 @@ class RelocVisitor {
return RelocToApply(); return RelocToApply();
} }
RelocToApply visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
switch (ObjToVisit.getArch()) {
default: break;
case Triple::x86_64:
switch (RelocType) {
default: break;
case MachO::X86_64_RELOC_UNSIGNED:
return visitMACHO_X86_64_UNSIGNED(R, Value);
}
}
HasError = true;
return RelocToApply();
}
int64_t getELFAddend32LE(RelocationRef R) { int64_t getELFAddend32LE(RelocationRef R) {
const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile()); const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile());
DataRefImpl DRI = R.getRawDataRefImpl(); DataRefImpl DRI = R.getRawDataRefImpl();
@ -252,6 +270,12 @@ class RelocVisitor {
Obj->getRelocationAddend(DRI, Addend); Obj->getRelocationAddend(DRI, Addend);
return Addend; return Addend;
} }
uint8_t getLengthMachO64(RelocationRef R) {
const MachOObjectFile *Obj = cast<MachOObjectFile>(R.getObjectFile());
return Obj->getRelocationLength(R.getRawDataRefImpl());
}
/// Operations /// Operations
/// 386-ELF /// 386-ELF
@ -413,6 +437,13 @@ class RelocVisitor {
RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) { RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
return RelocToApply(Value, /*Width=*/8); return RelocToApply(Value, /*Width=*/8);
} }
// X86_64 MachO
RelocToApply visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
uint8_t Length = getLengthMachO64(R);
Length = 1<<Length;
return RelocToApply(Value, Length);
}
}; };
} }

View File

@ -155,16 +155,6 @@ namespace COFF {
uint8_t NumberOfAuxSymbols; uint8_t NumberOfAuxSymbols;
}; };
enum SymbolFlags {
SF_TypeMask = 0x0000FFFF,
SF_TypeShift = 0,
SF_ClassMask = 0x00FF0000,
SF_ClassShift = 16,
SF_WeakExternal = 0x01000000
};
enum SymbolSectionNumber : int32_t { enum SymbolSectionNumber : int32_t {
IMAGE_SYM_DEBUG = -2, IMAGE_SYM_DEBUG = -2,
IMAGE_SYM_ABSOLUTE = -1, IMAGE_SYM_ABSOLUTE = -1,

View File

@ -1284,24 +1284,81 @@ template <class DataType, class StorageClass> class list_storage {
} }
}; };
// Define how to hold a class type object, such as a string. Since we can // Define how to hold a class type object, such as a string.
// inherit from a class, we do so. This makes us exactly compatible with the // Originally this code inherited from std::vector. In transitioning to a new
// object in all cases that it is used. // API for command line options we should change this. The new implementation
// of this list_storage specialization implements the minimum subset of the
// std::vector API required for all the current clients.
// //
template <class DataType> // FIXME: Reduce this API to a more narrow subset of std::vector
class list_storage<DataType, bool> : public std::vector<DataType> { //
template <class DataType> class list_storage<DataType, bool> {
std::vector<DataType> Storage;
public: public:
template <class T> void addValue(const T &V) { typedef typename std::vector<DataType>::iterator iterator;
std::vector<DataType>::push_back(V);
iterator begin() { return Storage.begin(); }
iterator end() { return Storage.end(); }
typedef typename std::vector<DataType>::const_iterator const_iterator;
const_iterator begin() const { return Storage.begin(); }
const_iterator end() const { return Storage.end(); }
typedef typename std::vector<DataType>::size_type size_type;
size_type size() const { return Storage.size(); }
bool empty() const { return Storage.empty(); }
void push_back(const DataType &value) { Storage.push_back(value); }
void push_back(DataType &&value) { Storage.push_back(value); }
typedef typename std::vector<DataType>::reference reference;
typedef typename std::vector<DataType>::const_reference const_reference;
reference operator[](size_type pos) { return Storage[pos]; }
const_reference operator[](size_type pos) const { return Storage[pos]; }
iterator erase(const_iterator pos) { return Storage.erase(pos); }
iterator erase(const_iterator first, const_iterator last) {
return Storage.erase(first, last);
} }
iterator erase(iterator pos) { return Storage.erase(pos); }
iterator erase(iterator first, iterator last) {
return Storage.erase(first, last);
}
iterator insert(const_iterator pos, const DataType &value) {
return Storage.insert(pos, value);
}
iterator insert(const_iterator pos, DataType &&value) {
return Storage.insert(pos, value);
}
iterator insert(iterator pos, const DataType &value) {
return Storage.insert(pos, value);
}
iterator insert(iterator pos, DataType &&value) {
return Storage.insert(pos, value);
}
reference front() { return Storage.front(); }
const_reference front() const { return Storage.front(); }
operator std::vector<DataType>&() { return Storage; }
operator ArrayRef<DataType>() { return Storage; }
std::vector<DataType> *operator&() { return &Storage; }
const std::vector<DataType> *operator&() const { return &Storage; }
template <class T> void addValue(const T &V) { Storage.push_back(V); }
}; };
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// list - A list of command line options. // list - A list of command line options.
// //
template <class DataType, class Storage = bool, template <class DataType, class StorageClass = bool,
class ParserClass = parser<DataType>> class ParserClass = parser<DataType>>
class list : public Option, public list_storage<DataType, Storage> { class list : public Option, public list_storage<DataType, StorageClass> {
std::vector<unsigned> Positions; std::vector<unsigned> Positions;
ParserClass Parser; ParserClass Parser;
@ -1319,7 +1376,7 @@ class list : public Option, public list_storage<DataType, Storage> {
typename ParserClass::parser_data_type(); typename ParserClass::parser_data_type();
if (Parser.parse(*this, ArgName, Arg, Val)) if (Parser.parse(*this, ArgName, Arg, Val))
return true; // Parse Error! return true; // Parse Error!
list_storage<DataType, Storage>::addValue(Val); list_storage<DataType, StorageClass>::addValue(Val);
setPosition(pos); setPosition(pos);
Positions.push_back(pos); Positions.push_back(pos);
return false; return false;

View File

@ -350,19 +350,6 @@
# define LLVM_ADDRESS_SANITIZER_BUILD 0 # define LLVM_ADDRESS_SANITIZER_BUILD 0
#endif #endif
/// \macro LLVM_IS_UNALIGNED_ACCESS_FAST
/// \brief Is unaligned memory access fast on the host machine.
///
/// Don't specialize on alignment for platforms where unaligned memory accesses
/// generates the same code as aligned memory accesses for common types.
#if defined(_M_AMD64) || defined(_M_IX86) || defined(__amd64) || \
defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || \
defined(_X86_) || defined(__i386) || defined(__i386__)
# define LLVM_IS_UNALIGNED_ACCESS_FAST 1
#else
# define LLVM_IS_UNALIGNED_ACCESS_FAST 0
#endif
/// \brief Mark debug helper function definitions like dump() that should not be /// \brief Mark debug helper function definitions like dump() that should not be
/// stripped from debug builds. /// stripped from debug builds.
// FIXME: Move this to a private config.h as it's not usable in public headers. // FIXME: Move this to a private config.h as it's not usable in public headers.

View File

@ -90,3 +90,11 @@ ELF_RELOC(R_HEX_IE_GOT_11_X, 82)
ELF_RELOC(R_HEX_TPREL_32_6_X, 83) ELF_RELOC(R_HEX_TPREL_32_6_X, 83)
ELF_RELOC(R_HEX_TPREL_16_X, 84) ELF_RELOC(R_HEX_TPREL_16_X, 84)
ELF_RELOC(R_HEX_TPREL_11_X, 85) ELF_RELOC(R_HEX_TPREL_11_X, 85)
ELF_RELOC(R_HEX_LD_PLT_B22_PCREL, 86)
ELF_RELOC(R_HEX_LD_GOT_LO16, 87)
ELF_RELOC(R_HEX_LD_GOT_HI16, 88)
ELF_RELOC(R_HEX_LD_GOT_32, 89)
ELF_RELOC(R_HEX_LD_GOT_16, 90)
ELF_RELOC(R_HEX_LD_GOT_32_6_X, 91)
ELF_RELOC(R_HEX_LD_GOT_16_X, 92)
ELF_RELOC(R_HEX_LD_GOT_11_X, 93)

View File

@ -562,7 +562,7 @@ inline uint64_t MinAlign(uint64_t A, uint64_t B) {
/// ///
/// Alignment should be a power of two. This method rounds up, so /// Alignment should be a power of two. This method rounds up, so
/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. /// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8.
inline uintptr_t alignAddr(void *Addr, size_t Alignment) { inline uintptr_t alignAddr(const void *Addr, size_t Alignment) {
assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && assert(Alignment && isPowerOf2_64((uint64_t)Alignment) &&
"Alignment is not a power of two!"); "Alignment is not a power of two!");
@ -573,7 +573,7 @@ inline uintptr_t alignAddr(void *Addr, size_t Alignment) {
/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment /// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment
/// bytes, rounding up. /// bytes, rounding up.
inline size_t alignmentAdjustment(void *Ptr, size_t Alignment) { inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) {
return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr;
} }

View File

@ -15,6 +15,10 @@
#ifndef LLVM_SUPPORT_TARGETPARSER_H #ifndef LLVM_SUPPORT_TARGETPARSER_H
#define LLVM_SUPPORT_TARGETPARSER_H #define LLVM_SUPPORT_TARGETPARSER_H
// FIXME: vector is used because that's what clang uses for subtarget feature
// lists, but SmallVector would probably be better
#include <vector>
namespace llvm { namespace llvm {
class StringRef; class StringRef;
@ -28,13 +32,16 @@ namespace ARM {
// FPU names. // FPU names.
enum FPUKind { enum FPUKind {
FK_INVALID = 0, FK_INVALID = 0,
FK_NONE,
FK_VFP, FK_VFP,
FK_VFPV2, FK_VFPV2,
FK_VFPV3, FK_VFPV3,
FK_VFPV3_D16, FK_VFPV3_D16,
FK_VFPV4, FK_VFPV4,
FK_VFPV4_D16, FK_VFPV4_D16,
FK_FPV4_SP_D16,
FK_FPV5_D16, FK_FPV5_D16,
FK_FPV5_SP_D16,
FK_FP_ARMV8, FK_FP_ARMV8,
FK_NEON, FK_NEON,
FK_NEON_VFPV4, FK_NEON_VFPV4,
@ -44,6 +51,20 @@ namespace ARM {
FK_LAST FK_LAST
}; };
// An FPU name implies one of three levels of Neon support:
enum NeonSupportLevel {
NS_None = 0, ///< No Neon
NS_Neon, ///< Neon
NS_Crypto ///< Neon with Crypto
};
// An FPU name restricts the FPU in one of three ways:
enum FPURestriction {
FR_None = 0, ///< No restriction
FR_D16, ///< Only 16 D registers
FR_SP_D16 ///< Only single-precision instructions, with 16 D registers
};
// Arch names. // Arch names.
enum ArchKind { enum ArchKind {
AK_INVALID = 0, AK_INVALID = 0,
@ -53,34 +74,34 @@ namespace ARM {
AK_ARMV3M, AK_ARMV3M,
AK_ARMV4, AK_ARMV4,
AK_ARMV4T, AK_ARMV4T,
AK_ARMV5,
AK_ARMV5T, AK_ARMV5T,
AK_ARMV5TE, AK_ARMV5TE,
AK_ARMV5TEJ,
AK_ARMV6, AK_ARMV6,
AK_ARMV6J,
AK_ARMV6K, AK_ARMV6K,
AK_ARMV6T2, AK_ARMV6T2,
AK_ARMV6Z, AK_ARMV6Z,
AK_ARMV6ZK, AK_ARMV6ZK,
AK_ARMV6M, AK_ARMV6M,
AK_ARMV7, AK_ARMV6SM,
AK_ARMV7A, AK_ARMV7A,
AK_ARMV7R, AK_ARMV7R,
AK_ARMV7M, AK_ARMV7M,
AK_ARMV7EM,
AK_ARMV8A, AK_ARMV8A,
AK_ARMV8_1A, AK_ARMV8_1A,
// Non-standard Arch names. // Non-standard Arch names.
AK_IWMMXT, AK_IWMMXT,
AK_IWMMXT2, AK_IWMMXT2,
AK_XSCALE, AK_XSCALE,
AK_ARMV5,
AK_ARMV5E, AK_ARMV5E,
AK_ARMV5TEJ, AK_ARMV6J,
AK_ARMV6SM,
AK_ARMV6HL, AK_ARMV6HL,
AK_ARMV7,
AK_ARMV7L, AK_ARMV7L,
AK_ARMV7HL, AK_ARMV7HL,
AK_ARMV7S, AK_ARMV7S,
AK_ARMV7EM,
AK_LAST AK_LAST
}; };
@ -92,8 +113,15 @@ namespace ARM {
AEK_FP, AEK_FP,
AEK_HWDIV, AEK_HWDIV,
AEK_MP, AEK_MP,
AEK_SIMD,
AEK_SEC, AEK_SEC,
AEK_VIRT, AEK_VIRT,
// Unsupported extensions.
AEK_OS,
AEK_IWMMXT,
AEK_IWMMXT2,
AEK_MAVERICK,
AEK_XSCALE,
AEK_LAST AEK_LAST
}; };
@ -132,9 +160,16 @@ class ARMTargetParser {
// Information by ID // Information by ID
static const char * getFPUName(unsigned FPUKind); static const char * getFPUName(unsigned FPUKind);
static unsigned getFPUVersion(unsigned FPUKind);
static unsigned getFPUNeonSupportLevel(unsigned FPUKind);
static unsigned getFPURestriction(unsigned FPUKind);
// FIXME: This should be moved to TargetTuple once it exists
static bool getFPUFeatures(unsigned FPUKind,
std::vector<const char*> &Features);
static const char * getArchName(unsigned ArchKind); static const char * getArchName(unsigned ArchKind);
static unsigned getArchDefaultCPUArch(unsigned ArchKind); static unsigned getArchAttr(unsigned ArchKind);
static const char * getArchDefaultCPUName(unsigned ArchKind); static const char * getCPUAttr(unsigned ArchKind);
static const char * getSubArch(unsigned ArchKind);
static const char * getArchExtName(unsigned ArchExtKind); static const char * getArchExtName(unsigned ArchExtKind);
static const char * getDefaultCPU(StringRef Arch); static const char * getDefaultCPU(StringRef Arch);

View File

@ -91,7 +91,7 @@ class Target {
typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch); typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch);
typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI, typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI,
StringRef TT); const Triple &TT);
typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, Reloc::Model RM, typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, Reloc::Model RM,
CodeModel::Model CM, CodeModel::Model CM,
CodeGenOpt::Level OL); CodeGenOpt::Level OL);
@ -287,15 +287,15 @@ class Target {
/// createMCAsmInfo - Create a MCAsmInfo implementation for the specified /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified
/// target triple. /// target triple.
/// ///
/// \param Triple This argument is used to determine the target machine /// \param TheTriple This argument is used to determine the target machine
/// feature set; it should always be provided. Generally this should be /// feature set; it should always be provided. Generally this should be
/// either the target triple from the module, or the target triple of the /// either the target triple from the module, or the target triple of the
/// host if that does not exist. /// host if that does not exist.
MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI, MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI,
StringRef Triple) const { StringRef TheTriple) const {
if (!MCAsmInfoCtorFn) if (!MCAsmInfoCtorFn)
return nullptr; return nullptr;
return MCAsmInfoCtorFn(MRI, Triple); return MCAsmInfoCtorFn(MRI, Triple(TheTriple));
} }
/// createMCCodeGenInfo - Create a MCCodeGenInfo implementation. /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation.
@ -889,7 +889,8 @@ template <class MCAsmInfoImpl> struct RegisterMCAsmInfo {
} }
private: private:
static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/, StringRef TT) { static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/,
const Triple &TT) {
return new MCAsmInfoImpl(TT); return new MCAsmInfoImpl(TT);
} }
}; };

View File

@ -1090,6 +1090,9 @@ class Input : public IO {
bool setCurrentDocument(); bool setCurrentDocument();
bool nextDocument(); bool nextDocument();
/// Returns the current node that's being parsed by the YAML Parser.
const Node *getCurrentNode() const;
private: private:
llvm::SourceMgr SrcMgr; // must be before Strm llvm::SourceMgr SrcMgr; // must be before Strm
std::unique_ptr<llvm::yaml::Stream> Strm; std::unique_ptr<llvm::yaml::Stream> Strm;
@ -1111,7 +1114,7 @@ class Input : public IO {
/// ///
class Output : public IO { class Output : public IO {
public: public:
Output(llvm::raw_ostream &, void *Ctxt=nullptr); Output(llvm::raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
~Output() override; ~Output() override;
bool outputting() override; bool outputting() override;
@ -1167,6 +1170,7 @@ class Output : public IO {
}; };
llvm::raw_ostream &Out; llvm::raw_ostream &Out;
int WrapColumn;
SmallVector<InState, 8> StateStack; SmallVector<InState, 8> StateStack;
int Column; int Column;
int ColumnAtFlowStart; int ColumnAtFlowStart;

View File

@ -17,48 +17,20 @@
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Allocator.h" #include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h" #include "llvm/Support/SMLoc.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <map> #include <map>
namespace llvm { namespace llvm {
// RecTy subclasses.
class BitRecTy;
class BitsRecTy;
class IntRecTy;
class StringRecTy;
class ListRecTy; class ListRecTy;
class DagRecTy; struct MultiClass;
class RecordRecTy;
// Init subclasses.
class Init;
class UnsetInit;
class BitInit;
class BitsInit;
class IntInit;
class StringInit;
class ListInit;
class UnOpInit;
class BinOpInit;
class TernOpInit;
class DefInit;
class DagInit;
class TypedInit;
class VarInit;
class FieldInit;
class VarBitInit;
class VarListElementInit;
// Other classes.
class Record; class Record;
class RecordVal; class RecordVal;
struct MultiClass;
class RecordKeeper; class RecordKeeper;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -81,12 +53,11 @@ class RecTy {
private: private:
RecTyKind Kind; RecTyKind Kind;
std::unique_ptr<ListRecTy> ListTy; std::unique_ptr<ListRecTy> ListTy;
virtual void anchor();
public: public:
RecTyKind getRecTyKind() const { return Kind; } RecTyKind getRecTyKind() const { return Kind; }
RecTy(RecTyKind K) : Kind(K), ListTy(nullptr) {} RecTy(RecTyKind K) : Kind(K) {}
virtual ~RecTy() {} virtual ~RecTy() {}
virtual std::string getAsString() const = 0; virtual std::string getAsString() const = 0;
@ -95,40 +66,10 @@ class RecTy {
/// typeIsConvertibleTo - Return true if all values of 'this' type can be /// typeIsConvertibleTo - Return true if all values of 'this' type can be
/// converted to the specified type. /// converted to the specified type.
virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0; virtual bool typeIsConvertibleTo(const RecTy *RHS) const;
/// getListTy - Returns the type representing list<this>. /// getListTy - Returns the type representing list<this>.
ListRecTy *getListTy(); ListRecTy *getListTy();
public: // These methods should only be called from subclasses of Init
virtual Init *convertValue( UnsetInit *UI) { return nullptr; }
virtual Init *convertValue( BitInit *BI) { return nullptr; }
virtual Init *convertValue( BitsInit *BI) { return nullptr; }
virtual Init *convertValue( IntInit *II) { return nullptr; }
virtual Init *convertValue(StringInit *SI) { return nullptr; }
virtual Init *convertValue( ListInit *LI) { return nullptr; }
virtual Init *convertValue( UnOpInit *UO) {
return convertValue((TypedInit*)UO);
}
virtual Init *convertValue( BinOpInit *BO) {
return convertValue((TypedInit*)BO);
}
virtual Init *convertValue( TernOpInit *TO) {
return convertValue((TypedInit*)TO);
}
virtual Init *convertValue(VarBitInit *VB) { return nullptr; }
virtual Init *convertValue( DefInit *DI) { return nullptr; }
virtual Init *convertValue( DagInit *DI) { return nullptr; }
virtual Init *convertValue( TypedInit *TI) { return nullptr; }
virtual Init *convertValue( VarInit *VI) {
return convertValue((TypedInit*)VI);
}
virtual Init *convertValue( FieldInit *FI) {
return convertValue((TypedInit*)FI);
}
public:
virtual bool baseClassOf(const RecTy*) const;
}; };
inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) { inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
@ -149,20 +90,9 @@ class BitRecTy : public RecTy {
static BitRecTy *get() { return &Shared; } static BitRecTy *get() { return &Shared; }
using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
Init *convertValue( BitInit *BI) override { return (Init*)BI; }
Init *convertValue( BitsInit *BI) override;
Init *convertValue( IntInit *II) override;
Init *convertValue(VarBitInit *VB) override { return (Init*)VB; }
Init *convertValue( TypedInit *TI) override;
std::string getAsString() const override { return "bit"; } std::string getAsString() const override { return "bit"; }
bool typeIsConvertibleTo(const RecTy *RHS) const override { bool typeIsConvertibleTo(const RecTy *RHS) const override;
return RHS->baseClassOf(this);
}
bool baseClassOf(const RecTy*) const override;
}; };
/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits /// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
@ -180,19 +110,9 @@ class BitsRecTy : public RecTy {
unsigned getNumBits() const { return Size; } unsigned getNumBits() const { return Size; }
using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override;
Init *convertValue( BitInit *UI) override;
Init *convertValue( BitsInit *BI) override;
Init *convertValue( IntInit *II) override;
Init *convertValue( TypedInit *TI) override;
std::string getAsString() const override; std::string getAsString() const override;
bool typeIsConvertibleTo(const RecTy *RHS) const override { bool typeIsConvertibleTo(const RecTy *RHS) const override;
return RHS->baseClassOf(this);
}
bool baseClassOf(const RecTy*) const override;
}; };
/// IntRecTy - 'int' - Represent an integer value of no particular size /// IntRecTy - 'int' - Represent an integer value of no particular size
@ -208,20 +128,9 @@ class IntRecTy : public RecTy {
static IntRecTy *get() { return &Shared; } static IntRecTy *get() { return &Shared; }
using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
Init *convertValue( BitInit *BI) override;
Init *convertValue( BitsInit *BI) override;
Init *convertValue( IntInit *II) override { return (Init*)II; }
Init *convertValue( TypedInit *TI) override;
std::string getAsString() const override { return "int"; } std::string getAsString() const override { return "int"; }
bool typeIsConvertibleTo(const RecTy *RHS) const override { bool typeIsConvertibleTo(const RecTy *RHS) const override;
return RHS->baseClassOf(this);
}
bool baseClassOf(const RecTy*) const override;
}; };
/// StringRecTy - 'string' - Represent an string value /// StringRecTy - 'string' - Represent an string value
@ -237,18 +146,7 @@ class StringRecTy : public RecTy {
static StringRecTy *get() { return &Shared; } static StringRecTy *get() { return &Shared; }
using RecTy::convertValue; std::string getAsString() const override;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
Init *convertValue(StringInit *SI) override { return (Init*)SI; }
Init *convertValue( UnOpInit *UO) override;
Init *convertValue( BinOpInit *BO) override;
Init *convertValue( TypedInit *TI) override;
std::string getAsString() const override { return "string"; }
bool typeIsConvertibleTo(const RecTy *RHS) const override {
return RHS->baseClassOf(this);
}
}; };
/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of /// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
@ -267,18 +165,9 @@ class ListRecTy : public RecTy {
static ListRecTy *get(RecTy *T) { return T->getListTy(); } static ListRecTy *get(RecTy *T) { return T->getListTy(); }
RecTy *getElementType() const { return Ty; } RecTy *getElementType() const { return Ty; }
using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
Init *convertValue( ListInit *LI) override;
Init *convertValue( TypedInit *TI) override;
std::string getAsString() const override; std::string getAsString() const override;
bool typeIsConvertibleTo(const RecTy *RHS) const override { bool typeIsConvertibleTo(const RecTy *RHS) const override;
return RHS->baseClassOf(this);
}
bool baseClassOf(const RecTy*) const override;
}; };
/// DagRecTy - 'dag' - Represent a dag fragment /// DagRecTy - 'dag' - Represent a dag fragment
@ -294,18 +183,7 @@ class DagRecTy : public RecTy {
static DagRecTy *get() { return &Shared; } static DagRecTy *get() { return &Shared; }
using RecTy::convertValue; std::string getAsString() const override;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
Init *convertValue( UnOpInit *UO) override;
Init *convertValue( BinOpInit *BO) override;
Init *convertValue( DagInit *DI) override { return (Init*)DI; }
Init *convertValue( TypedInit *TI) override;
std::string getAsString() const override { return "dag"; }
bool typeIsConvertibleTo(const RecTy *RHS) const override {
return RHS->baseClassOf(this);
}
}; };
/// RecordRecTy - '[classname]' - Represent an instance of a class, such as: /// RecordRecTy - '[classname]' - Represent an instance of a class, such as:
@ -325,17 +203,9 @@ class RecordRecTy : public RecTy {
Record *getRecord() const { return Rec; } Record *getRecord() const { return Rec; }
using RecTy::convertValue;
Init *convertValue( UnsetInit *UI) override { return (Init*)UI; }
Init *convertValue( DefInit *DI) override;
Init *convertValue( TypedInit *TI) override;
std::string getAsString() const override; std::string getAsString() const override;
bool typeIsConvertibleTo(const RecTy *RHS) const override { bool typeIsConvertibleTo(const RecTy *RHS) const override;
return RHS->baseClassOf(this);
}
bool baseClassOf(const RecTy*) const override;
}; };
/// resolveTypes - Find a common type that T1 and T2 convert to. /// resolveTypes - Find a common type that T1 and T2 convert to.
@ -418,10 +288,8 @@ class Init {
/// invokes print on stderr. /// invokes print on stderr.
void dump() const; void dump() const;
/// convertInitializerTo - This virtual function is a simple call-back /// convertInitializerTo - This virtual function converts to the appropriate
/// function that should be overridden to call the appropriate /// Init based on the passed in type.
/// RecTy::convertValue method.
///
virtual Init *convertInitializerTo(RecTy *Ty) const = 0; virtual Init *convertInitializerTo(RecTy *Ty) const = 0;
/// convertInitializerBitRange - This method is used to implement the bitrange /// convertInitializerBitRange - This method is used to implement the bitrange
@ -511,6 +379,8 @@ class TypedInit : public Init {
} }
RecTy *getType() const { return Ty; } RecTy *getType() const { return Ty; }
Init *convertInitializerTo(RecTy *Ty) const override;
Init * Init *
convertInitializerBitRange(const std::vector<unsigned> &Bits) const override; convertInitializerBitRange(const std::vector<unsigned> &Bits) const override;
Init * Init *
@ -535,7 +405,6 @@ class UnsetInit : public Init {
UnsetInit() : Init(IK_UnsetInit) {} UnsetInit() : Init(IK_UnsetInit) {}
UnsetInit(const UnsetInit &) = delete; UnsetInit(const UnsetInit &) = delete;
UnsetInit &operator=(const UnsetInit &Other) = delete; UnsetInit &operator=(const UnsetInit &Other) = delete;
void anchor() override;
public: public:
static bool classof(const Init *I) { static bool classof(const Init *I) {
@ -543,9 +412,7 @@ class UnsetInit : public Init {
} }
static UnsetInit *get(); static UnsetInit *get();
Init *convertInitializerTo(RecTy *Ty) const override { Init *convertInitializerTo(RecTy *Ty) const override;
return Ty->convertValue(const_cast<UnsetInit *>(this));
}
Init *getBit(unsigned Bit) const override { Init *getBit(unsigned Bit) const override {
return const_cast<UnsetInit*>(this); return const_cast<UnsetInit*>(this);
@ -563,7 +430,6 @@ class BitInit : public Init {
explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {} explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {}
BitInit(const BitInit &Other) = delete; BitInit(const BitInit &Other) = delete;
BitInit &operator=(BitInit &Other) = delete; BitInit &operator=(BitInit &Other) = delete;
void anchor() override;
public: public:
static bool classof(const Init *I) { static bool classof(const Init *I) {
@ -573,9 +439,7 @@ class BitInit : public Init {
bool getValue() const { return Value; } bool getValue() const { return Value; }
Init *convertInitializerTo(RecTy *Ty) const override { Init *convertInitializerTo(RecTy *Ty) const override;
return Ty->convertValue(const_cast<BitInit *>(this));
}
Init *getBit(unsigned Bit) const override { Init *getBit(unsigned Bit) const override {
assert(Bit < 1 && "Bit index out of range!"); assert(Bit < 1 && "Bit index out of range!");
@ -608,9 +472,7 @@ class BitsInit : public TypedInit, public FoldingSetNode {
unsigned getNumBits() const { return Bits.size(); } unsigned getNumBits() const { return Bits.size(); }
Init *convertInitializerTo(RecTy *Ty) const override { Init *convertInitializerTo(RecTy *Ty) const override;
return Ty->convertValue(const_cast<BitsInit *>(this));
}
Init * Init *
convertInitializerBitRange(const std::vector<unsigned> &Bits) const override; convertInitializerBitRange(const std::vector<unsigned> &Bits) const override;
@ -661,9 +523,7 @@ class IntInit : public TypedInit {
int64_t getValue() const { return Value; } int64_t getValue() const { return Value; }
Init *convertInitializerTo(RecTy *Ty) const override { Init *convertInitializerTo(RecTy *Ty) const override;
return Ty->convertValue(const_cast<IntInit *>(this));
}
Init * Init *
convertInitializerBitRange(const std::vector<unsigned> &Bits) const override; convertInitializerBitRange(const std::vector<unsigned> &Bits) const override;
@ -692,7 +552,6 @@ class StringInit : public TypedInit {
StringInit(const StringInit &Other) = delete; StringInit(const StringInit &Other) = delete;
StringInit &operator=(const StringInit &Other) = delete; StringInit &operator=(const StringInit &Other) = delete;
void anchor() override;
public: public:
static bool classof(const Init *I) { static bool classof(const Init *I) {
@ -702,9 +561,7 @@ class StringInit : public TypedInit {
const std::string &getValue() const { return Value; } const std::string &getValue() const { return Value; }
Init *convertInitializerTo(RecTy *Ty) const override { Init *convertInitializerTo(RecTy *Ty) const override;
return Ty->convertValue(const_cast<StringInit *>(this));
}
std::string getAsString() const override { return "\"" + Value + "\""; } std::string getAsString() const override { return "\"" + Value + "\""; }
std::string getAsUnquotedString() const override { return Value; } std::string getAsUnquotedString() const override { return Value; }
@ -746,7 +603,6 @@ class ListInit : public TypedInit, public FoldingSetNode {
void Profile(FoldingSetNodeID &ID) const; void Profile(FoldingSetNodeID &ID) const;
unsigned getSize() const { return Values.size(); }
Init *getElement(unsigned i) const { Init *getElement(unsigned i) const {
assert(i < Values.size() && "List element index out of range!"); assert(i < Values.size() && "List element index out of range!");
return Values[i]; return Values[i];
@ -757,9 +613,7 @@ class ListInit : public TypedInit, public FoldingSetNode {
Init * Init *
convertInitListSlice(const std::vector<unsigned> &Elements) const override; convertInitListSlice(const std::vector<unsigned> &Elements) const override;
Init *convertInitializerTo(RecTy *Ty) const override { Init *convertInitializerTo(RecTy *Ty) const override;
return Ty->convertValue(const_cast<ListInit *>(this));
}
/// resolveReferences - This method is used by classes that refer to other /// resolveReferences - This method is used by classes that refer to other
/// variables which may not be defined at the time they expression is formed. /// variables which may not be defined at the time they expression is formed.
@ -772,10 +626,11 @@ class ListInit : public TypedInit, public FoldingSetNode {
ArrayRef<Init*> getValues() const { return Values; } ArrayRef<Init*> getValues() const { return Values; }
inline const_iterator begin() const { return Values.begin(); } const_iterator begin() const { return Values.begin(); }
inline const_iterator end () const { return Values.end(); } const_iterator end () const { return Values.end(); }
inline bool empty() const { return Values.empty(); } size_t size () const { return Values.size(); }
bool empty() const { return Values.empty(); }
/// resolveListElementReference - This method is used to implement /// resolveListElementReference - This method is used to implement
/// VarListElementInit::resolveReferences. If the list element is resolvable /// VarListElementInit::resolveReferences. If the list element is resolvable
@ -805,17 +660,13 @@ class OpInit : public TypedInit {
// Clone - Clone this operator, replacing arguments with the new list // Clone - Clone this operator, replacing arguments with the new list
virtual OpInit *clone(std::vector<Init *> &Operands) const = 0; virtual OpInit *clone(std::vector<Init *> &Operands) const = 0;
virtual int getNumOperands() const = 0; virtual unsigned getNumOperands() const = 0;
virtual Init *getOperand(int i) const = 0; virtual Init *getOperand(unsigned i) const = 0;
// Fold - If possible, fold this to a simpler init. Return this if not // Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold. // possible to fold.
virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0; virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0;
Init *convertInitializerTo(RecTy *Ty) const override {
return Ty->convertValue(const_cast<OpInit *>(this));
}
Init *resolveListElementReference(Record &R, const RecordVal *RV, Init *resolveListElementReference(Record &R, const RecordVal *RV,
unsigned Elt) const override; unsigned Elt) const override;
@ -851,8 +702,8 @@ class UnOpInit : public OpInit {
return UnOpInit::get(getOpcode(), *Operands.begin(), getType()); return UnOpInit::get(getOpcode(), *Operands.begin(), getType());
} }
int getNumOperands() const override { return 1; } unsigned getNumOperands() const override { return 1; }
Init *getOperand(int i) const override { Init *getOperand(unsigned i) const override {
assert(i == 0 && "Invalid operand id for unary operator"); assert(i == 0 && "Invalid operand id for unary operator");
return getOperand(); return getOperand();
} }
@ -899,13 +750,12 @@ class BinOpInit : public OpInit {
return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType()); return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType());
} }
int getNumOperands() const override { return 2; } unsigned getNumOperands() const override { return 2; }
Init *getOperand(int i) const override { Init *getOperand(unsigned i) const override {
assert((i == 0 || i == 1) && "Invalid operand id for binary operator"); switch (i) {
if (i == 0) { default: llvm_unreachable("Invalid operand id for binary operator");
return getLHS(); case 0: return getLHS();
} else { case 1: return getRHS();
return getRHS();
} }
} }
@ -955,16 +805,13 @@ class TernOpInit : public OpInit {
getType()); getType());
} }
int getNumOperands() const override { return 3; } unsigned getNumOperands() const override { return 3; }
Init *getOperand(int i) const override { Init *getOperand(unsigned i) const override {
assert((i == 0 || i == 1 || i == 2) && switch (i) {
"Invalid operand id for ternary operator"); default: llvm_unreachable("Invalid operand id for ternary operator");
if (i == 0) { case 0: return getLHS();
return getLHS(); case 1: return getMHS();
} else if (i == 1) { case 2: return getRHS();
return getMHS();
} else {
return getRHS();
} }
} }
@ -1004,10 +851,6 @@ class VarInit : public TypedInit {
static VarInit *get(const std::string &VN, RecTy *T); static VarInit *get(const std::string &VN, RecTy *T);
static VarInit *get(Init *VN, RecTy *T); static VarInit *get(Init *VN, RecTy *T);
Init *convertInitializerTo(RecTy *Ty) const override {
return Ty->convertValue(const_cast<VarInit *>(this));
}
const std::string &getName() const; const std::string &getName() const;
Init *getNameInit() const { return VarName; } Init *getNameInit() const { return VarName; }
std::string getNameInitAsString() const { std::string getNameInitAsString() const {
@ -1056,9 +899,7 @@ class VarBitInit : public Init {
} }
static VarBitInit *get(TypedInit *T, unsigned B); static VarBitInit *get(TypedInit *T, unsigned B);
Init *convertInitializerTo(RecTy *Ty) const override { Init *convertInitializerTo(RecTy *Ty) const override;
return Ty->convertValue(const_cast<VarBitInit *>(this));
}
Init *getBitVar() const override { return TI; } Init *getBitVar() const override { return TI; }
unsigned getBitNum() const override { return Bit; } unsigned getBitNum() const override { return Bit; }
@ -1095,10 +936,6 @@ class VarListElementInit : public TypedInit {
} }
static VarListElementInit *get(TypedInit *T, unsigned E); static VarListElementInit *get(TypedInit *T, unsigned E);
Init *convertInitializerTo(RecTy *Ty) const override {
return Ty->convertValue(const_cast<VarListElementInit *>(this));
}
TypedInit *getVariable() const { return TI; } TypedInit *getVariable() const { return TI; }
unsigned getElementNum() const { return Element; } unsigned getElementNum() const { return Element; }
@ -1131,9 +968,7 @@ class DefInit : public TypedInit {
} }
static DefInit *get(Record*); static DefInit *get(Record*);
Init *convertInitializerTo(RecTy *Ty) const override { Init *convertInitializerTo(RecTy *Ty) const override;
return Ty->convertValue(const_cast<DefInit *>(this));
}
Record *getDef() const { return Def; } Record *getDef() const { return Def; }
@ -1179,10 +1014,6 @@ class FieldInit : public TypedInit {
static FieldInit *get(Init *R, const std::string &FN); static FieldInit *get(Init *R, const std::string &FN);
static FieldInit *get(Init *R, const Init *FN); static FieldInit *get(Init *R, const Init *FN);
Init *convertInitializerTo(RecTy *Ty) const override {
return Ty->convertValue(const_cast<FieldInit *>(this));
}
Init *getBit(unsigned Bit) const override; Init *getBit(unsigned Bit) const override;
Init *resolveListElementReference(Record &R, const RecordVal *RV, Init *resolveListElementReference(Record &R, const RecordVal *RV,
@ -1228,9 +1059,7 @@ class DagInit : public TypedInit, public FoldingSetNode {
void Profile(FoldingSetNodeID &ID) const; void Profile(FoldingSetNodeID &ID) const;
Init *convertInitializerTo(RecTy *Ty) const override { Init *convertInitializerTo(RecTy *Ty) const override;
return Ty->convertValue(const_cast<DagInit *>(this));
}
Init *getOperator() const { return Val; } Init *getOperator() const { return Val; }
@ -1280,22 +1109,21 @@ class DagInit : public TypedInit, public FoldingSetNode {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
class RecordVal { class RecordVal {
Init *Name; PointerIntPair<Init *, 1, bool> NameAndPrefix;
RecTy *Ty; RecTy *Ty;
unsigned Prefix;
Init *Value; Init *Value;
public: public:
RecordVal(Init *N, RecTy *T, unsigned P); RecordVal(Init *N, RecTy *T, bool P);
RecordVal(const std::string &N, RecTy *T, unsigned P); RecordVal(const std::string &N, RecTy *T, bool P);
const std::string &getName() const; const std::string &getName() const;
const Init *getNameInit() const { return Name; } const Init *getNameInit() const { return NameAndPrefix.getPointer(); }
std::string getNameInitAsString() const { std::string getNameInitAsString() const {
return getNameInit()->getAsUnquotedString(); return getNameInit()->getAsUnquotedString();
} }
unsigned getPrefix() const { return Prefix; } bool getPrefix() const { return NameAndPrefix.getInt(); }
RecTy *getType() const { return Ty; } RecTy *getType() const { return Ty; }
Init *getValue() const { return Value; } Init *getValue() const { return Value; }
@ -1344,7 +1172,7 @@ class Record {
// def Def : Class<Struct<i>>; // def Def : Class<Struct<i>>;
// //
// These need to get fully resolved before instantiating any other // These need to get fully resolved before instantiating any other
// definitions that usie them (e.g. Def). However, inside a multiclass they // definitions that use them (e.g. Def). However, inside a multiclass they
// can't be immediately resolved so we mark them ResolveFirst to fully // can't be immediately resolved so we mark them ResolveFirst to fully
// resolve them later as soon as the multiclass is instantiated. // resolve them later as soon as the multiclass is instantiated.
bool ResolveFirst; bool ResolveFirst;
@ -1354,13 +1182,6 @@ class Record {
public: public:
// Constructs a record. // Constructs a record.
explicit Record(const std::string &N, ArrayRef<SMLoc> locs,
RecordKeeper &records, bool Anonymous = false) :
ID(LastID++), Name(StringInit::get(N)), Locs(locs.begin(), locs.end()),
TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous),
ResolveFirst(false) {
init();
}
explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records, explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records,
bool Anonymous = false) : bool Anonymous = false) :
ID(LastID++), Name(N), Locs(locs.begin(), locs.end()), ID(LastID++), Name(N), Locs(locs.begin(), locs.end()),
@ -1368,6 +1189,10 @@ class Record {
ResolveFirst(false) { ResolveFirst(false) {
init(); init();
} }
explicit Record(const std::string &N, ArrayRef<SMLoc> locs,
RecordKeeper &records, bool Anonymous = false)
: Record(StringInit::get(N), locs, records, Anonymous) {}
// When copy-constructing a Record, we must still guarantee a globally unique // When copy-constructing a Record, we must still guarantee a globally unique
// ID number. All other fields can be copied normally. // ID number. All other fields can be copied normally.
@ -1406,8 +1231,8 @@ class Record {
ArrayRef<SMRange> getSuperClassRanges() const { return SuperClassRanges; } ArrayRef<SMRange> getSuperClassRanges() const { return SuperClassRanges; }
bool isTemplateArg(Init *Name) const { bool isTemplateArg(Init *Name) const {
for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i) for (Init *TA : TemplateArgs)
if (TemplateArgs[i] == Name) return true; if (TA == Name) return true;
return false; return false;
} }
bool isTemplateArg(StringRef Name) const { bool isTemplateArg(StringRef Name) const {
@ -1415,16 +1240,16 @@ class Record {
} }
const RecordVal *getValue(const Init *Name) const { const RecordVal *getValue(const Init *Name) const {
for (unsigned i = 0, e = Values.size(); i != e; ++i) for (const RecordVal &Val : Values)
if (Values[i].getNameInit() == Name) return &Values[i]; if (Val.getNameInit() == Name) return &Val;
return nullptr; return nullptr;
} }
const RecordVal *getValue(StringRef Name) const { const RecordVal *getValue(StringRef Name) const {
return getValue(StringInit::get(Name)); return getValue(StringInit::get(Name));
} }
RecordVal *getValue(const Init *Name) { RecordVal *getValue(const Init *Name) {
for (unsigned i = 0, e = Values.size(); i != e; ++i) for (RecordVal &Val : Values)
if (Values[i].getNameInit() == Name) return &Values[i]; if (Val.getNameInit() == Name) return &Val;
return nullptr; return nullptr;
} }
RecordVal *getValue(StringRef Name) { RecordVal *getValue(StringRef Name) {
@ -1465,15 +1290,15 @@ class Record {
} }
bool isSubClassOf(const Record *R) const { bool isSubClassOf(const Record *R) const {
for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) for (const Record *SC : SuperClasses)
if (SuperClasses[i] == R) if (SC == R)
return true; return true;
return false; return false;
} }
bool isSubClassOf(StringRef Name) const { bool isSubClassOf(StringRef Name) const {
for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) for (const Record *SC : SuperClasses)
if (SuperClasses[i]->getNameInitAsString() == Name) if (SC->getNameInitAsString() == Name)
return true; return true;
return false; return false;
} }
@ -1523,7 +1348,7 @@ class Record {
/// Return true if the named field is unset. /// Return true if the named field is unset.
bool isValueUnset(StringRef FieldName) const { bool isValueUnset(StringRef FieldName) const {
return getValueInit(FieldName) == UnsetInit::get(); return isa<UnsetInit>(getValueInit(FieldName));
} }
/// getValueAsString - This method looks up the specified field and returns /// getValueAsString - This method looks up the specified field and returns
@ -1675,7 +1500,6 @@ struct LessRecordFieldName {
}; };
struct LessRecordRegister { struct LessRecordRegister {
static size_t min(size_t a, size_t b) { return a < b ? a : b; }
static bool ascii_isdigit(char x) { return x >= '0' && x <= '9'; } static bool ascii_isdigit(char x) { return x >= '0' && x <= '9'; }
struct RecordParts { struct RecordParts {

View File

@ -47,9 +47,10 @@
#ifndef LLVM_TABLEGEN_SETTHEORY_H #ifndef LLVM_TABLEGEN_SETTHEORY_H
#define LLVM_TABLEGEN_SETTHEORY_H #define LLVM_TABLEGEN_SETTHEORY_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/Support/SourceMgr.h" #include "llvm/Support/SMLoc.h"
#include <map> #include <map>
#include <vector> #include <vector>
@ -58,7 +59,6 @@ namespace llvm {
class DagInit; class DagInit;
class Init; class Init;
class Record; class Record;
class RecordKeeper;
class SetTheory { class SetTheory {
public: public:

View File

@ -381,6 +381,7 @@ class Instruction {
bit hasPostISelHook = 0; // To be *adjusted* after isel by target hook. bit hasPostISelHook = 0; // To be *adjusted* after isel by target hook.
bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains? bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains?
bit isNotDuplicable = 0; // Is it unsafe to duplicate this instruction? bit isNotDuplicable = 0; // Is it unsafe to duplicate this instruction?
bit isConvergent = 0; // Is this instruction convergent?
bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction. bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction.
bit hasExtraSrcRegAllocReq = 0; // Sources have special regalloc requirement? bit hasExtraSrcRegAllocReq = 0; // Sources have special regalloc requirement?
bit hasExtraDefRegAllocReq = 0; // Defs have special regalloc requirement? bit hasExtraDefRegAllocReq = 0; // Defs have special regalloc requirement?
@ -506,7 +507,7 @@ class Requires<list<Predicate> preds> {
/// ops definition - This is just a simple marker used to identify the operand /// ops definition - This is just a simple marker used to identify the operand
/// list for an instruction. outs and ins are identical both syntactically and /// list for an instruction. outs and ins are identical both syntactically and
/// semanticallyr; they are used to define def operands and use operands to /// semantically; they are used to define def operands and use operands to
/// improve readibility. This should be used like this: /// improve readibility. This should be used like this:
/// (outs R32:$dst), (ins R32:$src1, R32:$src2) or something similar. /// (outs R32:$dst), (ins R32:$src1, R32:$src2) or something similar.
def ops; def ops;

View File

@ -711,20 +711,22 @@ class TargetInstrInfo : public MCInstrInfo {
/// Target-dependent implementation for foldMemoryOperand. /// Target-dependent implementation for foldMemoryOperand.
/// Target-independent code in foldMemoryOperand will /// Target-independent code in foldMemoryOperand will
/// take care of adding a MachineMemOperand to the newly created instruction. /// take care of adding a MachineMemOperand to the newly created instruction.
virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, /// The instruction and any auxiliary instructions necessary will be inserted
MachineInstr *MI, /// at InsertPt.
ArrayRef<unsigned> Ops, virtual MachineInstr *foldMemoryOperandImpl(
int FrameIndex) const { MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
MachineBasicBlock::iterator InsertPt, int FrameIndex) const {
return nullptr; return nullptr;
} }
/// Target-dependent implementation for foldMemoryOperand. /// Target-dependent implementation for foldMemoryOperand.
/// Target-independent code in foldMemoryOperand will /// Target-independent code in foldMemoryOperand will
/// take care of adding a MachineMemOperand to the newly created instruction. /// take care of adding a MachineMemOperand to the newly created instruction.
virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, /// The instruction and any auxiliary instructions necessary will be inserted
MachineInstr *MI, /// at InsertPt.
ArrayRef<unsigned> Ops, virtual MachineInstr *foldMemoryOperandImpl(
MachineInstr *LoadMI) const { MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI) const {
return nullptr; return nullptr;
} }

View File

@ -1431,7 +1431,8 @@ class TargetLoweringBase {
/// load/store. /// load/store.
virtual bool GetAddrModeArguments(IntrinsicInst * /*I*/, virtual bool GetAddrModeArguments(IntrinsicInst * /*I*/,
SmallVectorImpl<Value*> &/*Ops*/, SmallVectorImpl<Value*> &/*Ops*/,
Type *&/*AccessTy*/) const { Type *&/*AccessTy*/,
unsigned AddrSpace = 0) const {
return false; return false;
} }
@ -1456,7 +1457,12 @@ class TargetLoweringBase {
/// The type may be VoidTy, in which case only return true if the addressing /// The type may be VoidTy, in which case only return true if the addressing
/// mode is legal for a load/store of any legal type. TODO: Handle /// mode is legal for a load/store of any legal type. TODO: Handle
/// pre/postinc as well. /// pre/postinc as well.
virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const; ///
/// If the address space cannot be determined, it will be -1.
///
/// TODO: Remove default argument
virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty,
unsigned AddrSpace) const;
/// \brief Return the cost of the scaling factor used in the addressing mode /// \brief Return the cost of the scaling factor used in the addressing mode
/// represented by AM for this target, for a load/store of the specified type. /// represented by AM for this target, for a load/store of the specified type.
@ -1464,9 +1470,12 @@ class TargetLoweringBase {
/// If the AM is supported, the return value must be >= 0. /// If the AM is supported, the return value must be >= 0.
/// If the AM is not supported, it returns a negative value. /// If the AM is not supported, it returns a negative value.
/// TODO: Handle pre/postinc as well. /// TODO: Handle pre/postinc as well.
virtual int getScalingFactorCost(const AddrMode &AM, Type *Ty) const { /// TODO: Remove default argument
virtual int getScalingFactorCost(const AddrMode &AM, Type *Ty,
unsigned AS = 0) const {
// Default: assume that any scaling factor used in a legal AM is free. // Default: assume that any scaling factor used in a legal AM is free.
if (isLegalAddressingMode(AM, Ty)) return 0; if (isLegalAddressingMode(AM, Ty, AS))
return 0;
return -1; return -1;
} }

View File

@ -15,6 +15,7 @@
#ifndef LLVM_TARGET_TARGETOPTIONS_H #ifndef LLVM_TARGET_TARGETOPTIONS_H
#define LLVM_TARGET_TARGETOPTIONS_H #define LLVM_TARGET_TARGETOPTIONS_H
#include "llvm/Target/TargetRecip.h"
#include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/MCTargetOptions.h"
#include <string> #include <string>
@ -72,7 +73,8 @@ namespace llvm {
CompressDebugSections(false), FunctionSections(false), CompressDebugSections(false), FunctionSections(false),
DataSections(false), UniqueSectionNames(true), TrapUnreachable(false), DataSections(false), UniqueSectionNames(true), TrapUnreachable(false),
TrapFuncName(), FloatABIType(FloatABI::Default), TrapFuncName(), FloatABIType(FloatABI::Default),
AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single), AllowFPOpFusion(FPOpFusion::Standard), Reciprocals(TargetRecip()),
JTType(JumpTable::Single),
ThreadModel(ThreadModel::POSIX) {} ThreadModel(ThreadModel::POSIX) {}
/// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// PrintMachineCode - This flag is enabled when the -print-machineinstrs
@ -206,6 +208,9 @@ namespace llvm {
/// the value of this option. /// the value of this option.
FPOpFusion::FPOpFusionMode AllowFPOpFusion; FPOpFusion::FPOpFusionMode AllowFPOpFusion;
/// This class encapsulates options for reciprocal-estimate code generation.
TargetRecip Reciprocals;
/// JTType - This flag specifies the type of jump-instruction table to /// JTType - This flag specifies the type of jump-instruction table to
/// create for functions that have the jumptable attribute. /// create for functions that have the jumptable attribute.
JumpTable::JumpTableType JTType; JumpTable::JumpTableType JTType;
@ -240,6 +245,7 @@ inline bool operator==(const TargetOptions &LHS,
ARE_EQUAL(TrapFuncName) && ARE_EQUAL(TrapFuncName) &&
ARE_EQUAL(FloatABIType) && ARE_EQUAL(FloatABIType) &&
ARE_EQUAL(AllowFPOpFusion) && ARE_EQUAL(AllowFPOpFusion) &&
ARE_EQUAL(Reciprocals) &&
ARE_EQUAL(JTType) && ARE_EQUAL(JTType) &&
ARE_EQUAL(ThreadModel) && ARE_EQUAL(ThreadModel) &&
ARE_EQUAL(MCOptions); ARE_EQUAL(MCOptions);

View File

@ -0,0 +1,73 @@
//===--------------------- llvm/Target/TargetRecip.h ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class is used to customize machine-specific reciprocal estimate code
// generation in a target-independent way.
// If a target does not support operations in this specification, then code
// generation will default to using supported operations.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TARGET_TARGETRECIP_H
#define LLVM_TARGET_TARGETRECIP_H
#include "llvm/ADT/StringRef.h"
#include <vector>
#include <string>
#include <map>
namespace llvm {
struct TargetRecip {
public:
TargetRecip();
/// Initialize all or part of the operations from command-line options or
/// a front end.
TargetRecip(const std::vector<std::string> &Args);
/// Set whether a particular reciprocal operation is enabled and how many
/// refinement steps are needed when using it. Use "all" to set enablement
/// and refinement steps for all operations.
void setDefaults(const StringRef &Key, bool Enable, unsigned RefSteps);
/// Return true if the reciprocal operation has been enabled by default or
/// from the command-line. Return false if the operation has been disabled
/// by default or from the command-line.
bool isEnabled(const StringRef &Key) const;
/// Return the number of iterations necessary to refine the
/// the result of a machine instruction for the given reciprocal operation.
unsigned getRefinementSteps(const StringRef &Key) const;
bool operator==(const TargetRecip &Other) const;
private:
enum {
Uninitialized = -1
};
struct RecipParams {
int8_t Enabled;
int8_t RefinementSteps;
RecipParams() : Enabled(Uninitialized), RefinementSteps(Uninitialized) {}
};
std::map<StringRef, RecipParams> RecipMap;
typedef std::map<StringRef, RecipParams>::iterator RecipIter;
typedef std::map<StringRef, RecipParams>::const_iterator ConstRecipIter;
bool parseGlobalParams(const std::string &Arg);
void parseIndividualParams(const std::vector<std::string> &Args);
};
} // End llvm namespace
#endif

View File

@ -16,10 +16,12 @@
#define LLVM_TRANSFORMS_SCALAR_H #define LLVM_TRANSFORMS_SCALAR_H
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include <functional>
namespace llvm { namespace llvm {
class BasicBlockPass; class BasicBlockPass;
class Function;
class FunctionPass; class FunctionPass;
class ModulePass; class ModulePass;
class Pass; class Pass;
@ -152,7 +154,14 @@ Pass *createLoopInterchangePass();
// //
Pass *createLoopStrengthReducePass(); Pass *createLoopStrengthReducePass();
Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset); //===----------------------------------------------------------------------===//
//
// GlobalMerge - This pass merges internal (by default) globals into structs
// to enable reuse of a base pointer by indexed addressing modes.
// It can also be configured to focus on size optimizations only.
//
Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset,
bool OnlyOptimizeForSize = false);
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
@ -238,7 +247,8 @@ FunctionPass *createJumpThreadingPass(int Threshold = -1);
// CFGSimplification - Merge basic blocks, eliminate unreachable blocks, // CFGSimplification - Merge basic blocks, eliminate unreachable blocks,
// simplify terminator instructions, etc... // simplify terminator instructions, etc...
// //
FunctionPass *createCFGSimplificationPass(int Threshold = -1); FunctionPass *createCFGSimplificationPass(
int Threshold = -1, std::function<bool(const Function &)> Ftor = nullptr);
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
@ -456,7 +466,7 @@ FunctionPass *createPlaceSafepointsPass();
// RewriteStatepointsForGC - Rewrite any gc.statepoints which do not yet have // RewriteStatepointsForGC - Rewrite any gc.statepoints which do not yet have
// explicit relocations to include explicit relocations. // explicit relocations to include explicit relocations.
// //
FunctionPass *createRewriteStatepointsForGCPass(); ModulePass *createRewriteStatepointsForGCPass();
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //

Some files were not shown because too many files have changed in this diff Show More