Update Makefiles and other build glue for llvm/clang 3.7.0, as of trunk
r239412.
This commit is contained in:
commit
97bc6c731e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/clang-trunk/; revision=284236
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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; }
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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.
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
///
|
///
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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");
|
||||||
|
137
contrib/llvm/include/llvm/Analysis/MemoryLocation.h
Normal file
137
contrib/llvm/include/llvm/Analysis/MemoryLocation.h
Normal 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
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
47
contrib/llvm/include/llvm/CodeGen/DIEValue.def
Normal file
47
contrib/llvm/include/llvm/CodeGen/DIEValue.def
Normal 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
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
52
contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h
Normal file
52
contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h
Normal 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
|
40
contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h
Normal file
40
contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h
Normal 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
|
@ -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
|
||||||
|
@ -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.
|
||||||
///
|
///
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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)),
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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],
|
||||||
|
@ -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]>;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
///
|
///
|
||||||
|
@ -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&);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
///
|
///
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
@ -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
|
||||||
|
@ -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() {
|
||||||
|
@ -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
|
|
@ -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.
|
||||||
///
|
///
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
64
contrib/llvm/include/llvm/MC/MCSymbolCOFF.h
Normal file
64
contrib/llvm/include/llvm/MC/MCSymbolCOFF.h
Normal 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
|
57
contrib/llvm/include/llvm/MC/MCSymbolELF.h
Normal file
57
contrib/llvm/include/llvm/MC/MCSymbolELF.h
Normal 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
|
123
contrib/llvm/include/llvm/MC/MCSymbolMachO.h
Normal file
123
contrib/llvm/include/llvm/MC/MCSymbolMachO.h
Normal 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
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
51
contrib/llvm/include/llvm/Object/ArchiveWriter.h
Normal file
51
contrib/llvm/include/llvm/Object/ArchiveWriter.h
Normal 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
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
73
contrib/llvm/include/llvm/Target/TargetRecip.h
Normal file
73
contrib/llvm/include/llvm/Target/TargetRecip.h
Normal 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
|
@ -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
Loading…
Reference in New Issue
Block a user