Update Makefiles and other build glue for llvm/clang 3.7.0, as of trunk
r239412.
This commit is contained in:
commit
97bc6c731e
@ -997,6 +997,13 @@ unsigned LLVMCountStructElementTypes(LLVMTypeRef StructTy);
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -58,6 +58,24 @@ LLVMBool LLVMLoadLibraryPermanently(const char* Filename);
|
||||
void LLVMParseCommandLineOptions(int argc, const char *const *argv,
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
@ -351,8 +351,7 @@ class APInt {
|
||||
/// This checks to see if the value of this APInt is the maximum signed
|
||||
/// value for the APInt's bit width.
|
||||
bool isMaxSignedValue() const {
|
||||
return BitWidth == 1 ? VAL == 0
|
||||
: !isNegative() && countPopulation() == BitWidth - 1;
|
||||
return !isNegative() && countPopulation() == BitWidth - 1;
|
||||
}
|
||||
|
||||
/// \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
|
||||
/// value for the APInt's bit width.
|
||||
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.
|
||||
|
@ -50,7 +50,8 @@ class Triple {
|
||||
armeb, // ARM (big endian): armeb
|
||||
aarch64, // AArch64 (little endian): aarch64
|
||||
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
|
||||
mips, // MIPS: mips, mipsallegrex
|
||||
mipsel, // MIPSEL: mipsel, mipsallegrexel
|
||||
@ -255,6 +256,15 @@ class Triple {
|
||||
/// getEnvironment - Get the parsed environment type of this triple.
|
||||
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.
|
||||
ObjectFormatType getObjectFormat() const { return ObjectFormat; }
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/Analysis/MemoryLocation.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -82,7 +83,7 @@ class AliasAnalysis {
|
||||
/// 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.
|
||||
static uint64_t const UnknownSize = ~UINT64_C(0);
|
||||
static uint64_t const UnknownSize = MemoryLocation::UnknownSize;
|
||||
|
||||
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
|
||||
/// object, or null if no TargetLibraryInfo object is available.
|
||||
@ -98,70 +99,9 @@ class AliasAnalysis {
|
||||
/// Alias Queries...
|
||||
///
|
||||
|
||||
/// Location - A description of a memory location.
|
||||
struct Location {
|
||||
/// Ptr - The address of the start of the 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");
|
||||
}
|
||||
/// Legacy typedef for the AA location object. New code should use \c
|
||||
/// MemoryLocation directly.
|
||||
typedef MemoryLocation Location;
|
||||
|
||||
/// 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
|
||||
@ -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
|
||||
/// function.
|
||||
bool isNoAliasCall(const Value *V);
|
||||
|
@ -191,8 +191,8 @@ class BlockFrequencyInfoImplBase {
|
||||
|
||||
/// \brief Data about a loop.
|
||||
///
|
||||
/// Contains the data necessary to represent represent a loop as a
|
||||
/// pseudo-node once it's packaged.
|
||||
/// Contains the data necessary to represent a loop as a pseudo-node once it's
|
||||
/// packaged.
|
||||
struct LoopData {
|
||||
typedef SmallVector<std::pair<BlockNode, BlockMass>, 4> ExitMap;
|
||||
typedef SmallVector<BlockNode, 4> NodeList;
|
||||
@ -930,7 +930,7 @@ void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F,
|
||||
initializeRPOT();
|
||||
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.
|
||||
computeMassInLoops();
|
||||
computeMassInFunction();
|
||||
|
@ -47,6 +47,9 @@ class BranchProbabilityInfo : public FunctionPass {
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
bool runOnFunction(Function &F) override;
|
||||
|
||||
void releaseMemory() 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.
|
||||
|
@ -230,7 +230,7 @@ class CallGraphNode {
|
||||
void addCalledFunction(CallSite CS, CallGraphNode *M) {
|
||||
assert(!CS.getInstruction() || !CS.getCalledFunction() ||
|
||||
!CS.getCalledFunction()->isIntrinsic());
|
||||
CalledFunctions.push_back(std::make_pair(CS.getInstruction(), M));
|
||||
CalledFunctions.emplace_back(CS.getInstruction(), M);
|
||||
M->AddRef();
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H
|
||||
|
||||
#include "llvm/ADT/SmallBitVector.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
@ -520,11 +521,11 @@ namespace llvm {
|
||||
/// in LoopNest.
|
||||
bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const;
|
||||
|
||||
/// Makes sure both subscripts (i.e. Pair->Src and Pair->Dst) share the same
|
||||
/// integer type by sign-extending one of them when necessary.
|
||||
/// Makes sure all subscript pairs share the same integer type by
|
||||
/// sign-extending as necessary.
|
||||
/// Sign-extending a subscript is safe because getelementptr assumes the
|
||||
/// array subscripts are signed.
|
||||
void unifySubscriptType(Subscript *Pair);
|
||||
/// array subscripts are signed.
|
||||
void unifySubscriptType(ArrayRef<Subscript *> Pairs);
|
||||
|
||||
/// removeMatchingExtensions - Examines a subscript pair.
|
||||
/// If the source and destination are identically sign (or zero)
|
||||
|
@ -345,6 +345,10 @@ class LoopAccessInfo {
|
||||
/// to needsChecking.
|
||||
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.
|
||||
///
|
||||
/// 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
|
||||
/// 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
|
||||
/// to be vectorized.
|
||||
@ -460,10 +467,6 @@ class LoopAccessInfo {
|
||||
/// loop-independent and loop-carried dependences between memory accesses.
|
||||
MemoryDepChecker DepChecker;
|
||||
|
||||
/// \brief Number of memchecks required to prove independence of otherwise
|
||||
/// may-alias pointers
|
||||
unsigned NumComparisons;
|
||||
|
||||
Loop *TheLoop;
|
||||
ScalarEvolution *SE;
|
||||
const DataLayout &DL;
|
||||
@ -501,6 +504,11 @@ const SCEV *replaceSymbolicStrideSCEV(ScalarEvolution *SE,
|
||||
const ValueToValueMap &PtrToStride,
|
||||
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
|
||||
/// of a loop.
|
||||
///
|
||||
|
@ -47,13 +47,6 @@ namespace llvm {
|
||||
template <typename IRUnitT> class AnalysisManager;
|
||||
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 LoopInfo;
|
||||
class Loop;
|
||||
@ -324,7 +317,10 @@ class LoopBase {
|
||||
/// current loop, updating the Blocks as appropriate. This does not update
|
||||
/// the mapping in the LoopInfo class.
|
||||
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);
|
||||
}
|
||||
|
||||
@ -493,7 +489,7 @@ class Loop : public LoopBase<BasicBlock, Loop> {
|
||||
template<class BlockT, class LoopT>
|
||||
class LoopInfoBase {
|
||||
// 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;
|
||||
friend class LoopBase<BlockT, LoopT>;
|
||||
friend class LoopInfo;
|
||||
@ -543,9 +539,7 @@ class LoopInfoBase {
|
||||
/// 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.
|
||||
///
|
||||
LoopT *getLoopFor(const BlockT *BB) const {
|
||||
return BBMap.lookup(const_cast<BlockT*>(BB));
|
||||
}
|
||||
LoopT *getLoopFor(const BlockT *BB) const { return BBMap.lookup(BB); }
|
||||
|
||||
/// operator[] - same as getLoopFor...
|
||||
///
|
||||
@ -562,7 +556,7 @@ class LoopInfoBase {
|
||||
}
|
||||
|
||||
// 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);
|
||||
return L && L->getHeader() == BB;
|
||||
}
|
||||
@ -729,12 +723,6 @@ class LoopAnalysis {
|
||||
/// \brief Provide a name for the analysis for debugging and logging.
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -527,7 +527,7 @@ void LoopInfoBase<BlockT, LoopT>::verify() const {
|
||||
// Verify that blocks are mapped to valid loops.
|
||||
#ifndef NDEBUG
|
||||
for (auto &Entry : BBMap) {
|
||||
BlockT *BB = Entry.first;
|
||||
const BlockT *BB = Entry.first;
|
||||
LoopT *L = Entry.second;
|
||||
assert(Loops.count(L) && "orphaned loop");
|
||||
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;
|
||||
|
||||
/// PHITranslateValue - PHI translate the current address up the CFG from
|
||||
/// CurBB to Pred, updating our state to reflect any needed changes. If the
|
||||
/// dominator tree DT is non-null, the translated value must dominate
|
||||
/// CurBB to Pred, updating our state to reflect any needed changes. If
|
||||
/// 'MustDominate' is true, the translated value must dominate
|
||||
/// PredBB. This returns true on failure and sets Addr to null.
|
||||
bool PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const DominatorTree *DT);
|
||||
|
||||
const DominatorTree *DT, bool MustDominate);
|
||||
|
||||
/// PHITranslateWithInsertion - PHI translate this value into the specified
|
||||
/// predecessor block, inserting a computation of the value if it is
|
||||
/// unavailable.
|
||||
|
@ -221,19 +221,21 @@ class TargetTransformInfo {
|
||||
|
||||
/// Parameters that control the generic loop unrolling transformation.
|
||||
struct UnrollingPreferences {
|
||||
/// The cost threshold for the unrolled loop, compared to
|
||||
/// CodeMetrics.NumInsts aggregated over all basic blocks in the loop body.
|
||||
/// The unrolling factor is set such that the unrolled loop body does not
|
||||
/// exceed this cost. Set this to UINT_MAX to disable the loop body cost
|
||||
/// The cost threshold for the unrolled loop. Should be relative to the
|
||||
/// getUserCost values returned by this API, and the expectation is that
|
||||
/// the unrolled loop's instructions when run through that interface should
|
||||
/// 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.
|
||||
unsigned Threshold;
|
||||
/// If complete unrolling could help other optimizations (e.g. InstSimplify)
|
||||
/// to remove N% of instructions, then we can go beyond unroll threshold.
|
||||
/// This value set the minimal percent for allowing that.
|
||||
unsigned MinPercentOfOptimized;
|
||||
/// The absolute cost threshold. We won't go beyond this even if complete
|
||||
/// unrolling could result in optimizing out 90% of instructions.
|
||||
unsigned AbsoluteThreshold;
|
||||
/// If complete unrolling will reduce the cost of the loop below its
|
||||
/// expected dynamic cost while rolled by this percentage, apply a discount
|
||||
/// (below) to its unrolled cost.
|
||||
unsigned PercentDynamicCostSavedThreshold;
|
||||
/// The discount applied to the unrolled cost when the *dynamic* cost
|
||||
/// savings of unrolling exceed the \c PercentDynamicCostSavedThreshold.
|
||||
unsigned DynamicCostSavingsDiscount;
|
||||
/// The cost threshold for the unrolled loop when optimizing for size (set
|
||||
/// to UINT_MAX to disable).
|
||||
unsigned OptSizeThreshold;
|
||||
@ -303,7 +305,8 @@ class TargetTransformInfo {
|
||||
/// mode is legal for a load/store of any legal type.
|
||||
/// TODO: Handle pre/postinc as well.
|
||||
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
|
||||
/// 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.
|
||||
/// TODO: Handle pre/postinc as well.
|
||||
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
|
||||
/// 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 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.
|
||||
///
|
||||
/// 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 isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
|
||||
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 isLegalMaskedLoad(Type *DataType, int Consecutive) = 0;
|
||||
virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
|
||||
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 isProfitableToHoist(Instruction *I) = 0;
|
||||
virtual bool isTypeLegal(Type *Ty) = 0;
|
||||
@ -582,6 +601,11 @@ class TargetTransformInfo::Concept {
|
||||
virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src,
|
||||
unsigned Alignment,
|
||||
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,
|
||||
bool IsPairwiseForm) = 0;
|
||||
virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
|
||||
@ -648,9 +672,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
|
||||
return Impl.isLegalICmpImmediate(Imm);
|
||||
}
|
||||
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,
|
||||
Scale);
|
||||
Scale, AddrSpace);
|
||||
}
|
||||
bool isLegalMaskedStore(Type *DataType, int Consecutive) override {
|
||||
return Impl.isLegalMaskedStore(DataType, Consecutive);
|
||||
@ -659,8 +684,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
|
||||
return Impl.isLegalMaskedLoad(DataType, Consecutive);
|
||||
}
|
||||
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) override {
|
||||
return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg, Scale);
|
||||
bool HasBaseReg, int64_t Scale,
|
||||
unsigned AddrSpace) override {
|
||||
return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg,
|
||||
Scale, AddrSpace);
|
||||
}
|
||||
bool isTruncateFree(Type *Ty1, Type *Ty2) override {
|
||||
return Impl.isTruncateFree(Ty1, Ty2);
|
||||
@ -740,6 +767,14 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
|
||||
unsigned AddressSpace) override {
|
||||
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,
|
||||
bool IsPairwiseForm) override {
|
||||
return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm);
|
||||
|
@ -207,7 +207,8 @@ class TargetTransformInfoImplBase {
|
||||
bool isLegalICmpImmediate(int64_t Imm) { return false; }
|
||||
|
||||
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
|
||||
// taken from the implementation of LSR.
|
||||
return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1);
|
||||
@ -218,9 +219,10 @@ class TargetTransformInfoImplBase {
|
||||
bool isLegalMaskedLoad(Type *DataType, int Consecutive) { return false; }
|
||||
|
||||
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.
|
||||
if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale))
|
||||
if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg,
|
||||
Scale, AddrSpace))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
@ -300,6 +302,14 @@ class TargetTransformInfoImplBase {
|
||||
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,
|
||||
ArrayRef<Type *> Tys) {
|
||||
return 1;
|
||||
|
@ -113,7 +113,7 @@ class BitstreamReader {
|
||||
return *const_cast<BlockInfo*>(BI);
|
||||
|
||||
// Otherwise, add a new record.
|
||||
BlockInfoRecords.push_back(BlockInfo());
|
||||
BlockInfoRecords.emplace_back();
|
||||
BlockInfoRecords.back().BlockID = BlockID;
|
||||
return BlockInfoRecords.back();
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ class BitstreamWriter {
|
||||
|
||||
// Push the outer block's abbrev set onto the stack, start out with an
|
||||
// empty abbrev set.
|
||||
BlockScope.push_back(Block(OldCodeSize, BlockSizeWordIndex));
|
||||
BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex);
|
||||
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
|
||||
|
||||
// If there is a blockinfo for this BlockID, add all the predefined abbrevs
|
||||
@ -503,7 +503,7 @@ class BitstreamWriter {
|
||||
return *BI;
|
||||
|
||||
// Otherwise, add a new record.
|
||||
BlockInfoRecords.push_back(BlockInfo());
|
||||
BlockInfoRecords.emplace_back();
|
||||
BlockInfoRecords.back().BlockID = BlockID;
|
||||
return BlockInfoRecords.back();
|
||||
}
|
||||
|
@ -125,23 +125,24 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
|
||||
}
|
||||
|
||||
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) {
|
||||
bool HasBaseReg, int64_t Scale,
|
||||
unsigned AddrSpace) {
|
||||
TargetLoweringBase::AddrMode AM;
|
||||
AM.BaseGV = BaseGV;
|
||||
AM.BaseOffs = BaseOffset;
|
||||
AM.HasBaseReg = HasBaseReg;
|
||||
AM.Scale = Scale;
|
||||
return getTLI()->isLegalAddressingMode(AM, Ty);
|
||||
return getTLI()->isLegalAddressingMode(AM, Ty, AddrSpace);
|
||||
}
|
||||
|
||||
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) {
|
||||
bool HasBaseReg, int64_t Scale, unsigned AddrSpace) {
|
||||
TargetLoweringBase::AddrMode AM;
|
||||
AM.BaseGV = BaseGV;
|
||||
AM.BaseOffs = BaseOffset;
|
||||
AM.HasBaseReg = HasBaseReg;
|
||||
AM.Scale = Scale;
|
||||
return getTLI()->getScalingFactorCost(AM, Ty);
|
||||
return getTLI()->getScalingFactorCost(AM, Ty, AddrSpace);
|
||||
}
|
||||
|
||||
bool isTruncateFree(Type *Ty1, Type *Ty2) {
|
||||
@ -522,6 +523,73 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
|
||||
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,
|
||||
ArrayRef<Type *> Tys) {
|
||||
unsigned ISD = 0;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Target/TargetRecip.h"
|
||||
#include <string>
|
||||
using namespace llvm;
|
||||
|
||||
@ -152,6 +153,12 @@ FuseFPOps("fp-contract",
|
||||
"Only fuse FP ops when the result won't be effected."),
|
||||
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>
|
||||
DontPlaceZerosInBSS("nozero-initialized-in-bss",
|
||||
cl::desc("Don't place zero-initialized symbols into bss section"),
|
||||
@ -230,6 +237,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
|
||||
TargetOptions Options;
|
||||
Options.LessPreciseFPMADOption = EnableFPMAD;
|
||||
Options.AllowFPOpFusion = FuseFPOps;
|
||||
Options.Reciprocals = TargetRecip(ReciprocalOps);
|
||||
Options.UnsafeFPMath = EnableUnsafeFPMath;
|
||||
Options.NoInfsFPMath = EnableNoInfsFPMath;
|
||||
Options.NoNaNsFPMath = EnableNoNaNsFPMath;
|
||||
|
@ -104,154 +104,14 @@ class DIEAbbrev : public FoldingSetNode {
|
||||
#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.
|
||||
///
|
||||
class DIEInteger : public DIEValue {
|
||||
friend DIEValue;
|
||||
|
||||
class DIEInteger {
|
||||
uint64_t Integer;
|
||||
|
||||
public:
|
||||
explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
|
||||
explicit DIEInteger(uint64_t I) : Integer(I) {}
|
||||
|
||||
/// BestForm - Choose the best form for integer.
|
||||
///
|
||||
@ -278,120 +138,91 @@ class DIEInteger : public DIEValue {
|
||||
uint64_t getValue() const { return Integer; }
|
||||
void setValue(uint64_t Val) { Integer = Val; }
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *I) { return I->getType() == isInteger; }
|
||||
|
||||
private:
|
||||
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void printImpl(raw_ostream &O) const;
|
||||
void print(raw_ostream &O) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEExpr - An expression DIE.
|
||||
//
|
||||
class DIEExpr : public DIEValue {
|
||||
friend class DIEValue;
|
||||
|
||||
class DIEExpr {
|
||||
const MCExpr *Expr;
|
||||
|
||||
public:
|
||||
explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {}
|
||||
explicit DIEExpr(const MCExpr *E) : Expr(E) {}
|
||||
|
||||
/// getValue - Get MCExpr.
|
||||
///
|
||||
const MCExpr *getValue() const { return Expr; }
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *E) { return E->getType() == isExpr; }
|
||||
|
||||
private:
|
||||
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void printImpl(raw_ostream &O) const;
|
||||
void print(raw_ostream &O) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIELabel - A label DIE.
|
||||
//
|
||||
class DIELabel : public DIEValue {
|
||||
friend class DIEValue;
|
||||
|
||||
class DIELabel {
|
||||
const MCSymbol *Label;
|
||||
|
||||
public:
|
||||
explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {}
|
||||
explicit DIELabel(const MCSymbol *L) : Label(L) {}
|
||||
|
||||
/// getValue - Get MCSymbol.
|
||||
///
|
||||
const MCSymbol *getValue() const { return Label; }
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
|
||||
|
||||
private:
|
||||
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void printImpl(raw_ostream &O) const;
|
||||
void print(raw_ostream &O) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEDelta - A simple label difference DIE.
|
||||
///
|
||||
class DIEDelta : public DIEValue {
|
||||
friend class DIEValue;
|
||||
|
||||
class DIEDelta {
|
||||
const MCSymbol *LabelHi;
|
||||
const MCSymbol *LabelLo;
|
||||
|
||||
public:
|
||||
DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo)
|
||||
: DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
|
||||
DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) : LabelHi(Hi), LabelLo(Lo) {}
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *D) { return D->getType() == isDelta; }
|
||||
|
||||
private:
|
||||
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void printImpl(raw_ostream &O) const;
|
||||
void print(raw_ostream &O) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEString - A container for string values.
|
||||
///
|
||||
class DIEString : public DIEValue {
|
||||
friend class DIEValue;
|
||||
|
||||
class DIEString {
|
||||
DwarfStringPoolEntryRef S;
|
||||
|
||||
public:
|
||||
DIEString(DwarfStringPoolEntryRef S) : DIEValue(isString), S(S) {}
|
||||
DIEString(DwarfStringPoolEntryRef S) : S(S) {}
|
||||
|
||||
/// getString - Grab the string out of the object.
|
||||
StringRef getString() const { return S.getString(); }
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *D) { return D->getType() == isString; }
|
||||
|
||||
private:
|
||||
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void printImpl(raw_ostream &O) const;
|
||||
void print(raw_ostream &O) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -399,72 +230,350 @@ class DIEString : public DIEValue {
|
||||
/// 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
|
||||
/// yet defined (ie. types.)
|
||||
class DIEEntry : public DIEValue {
|
||||
friend class DIEValue;
|
||||
class DIE;
|
||||
class DIEEntry {
|
||||
DIE *Entry;
|
||||
|
||||
DIE &Entry;
|
||||
DIEEntry() = delete;
|
||||
|
||||
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.
|
||||
static unsigned getRefAddrSize(const AsmPrinter *AP);
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *E) { return E->getType() == isEntry; }
|
||||
|
||||
private:
|
||||
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const {
|
||||
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
||||
return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP)
|
||||
: sizeof(int32_t);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void printImpl(raw_ostream &O) const;
|
||||
void print(raw_ostream &O) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// \brief A signature reference to a type unit.
|
||||
class DIETypeSignature : public DIEValue {
|
||||
friend class DIEValue;
|
||||
class DIETypeSignature {
|
||||
const DwarfTypeUnit *Unit;
|
||||
|
||||
const DwarfTypeUnit &Unit;
|
||||
DIETypeSignature() = delete;
|
||||
|
||||
public:
|
||||
explicit DIETypeSignature(const DwarfTypeUnit &Unit)
|
||||
: DIEValue(isTypeSignature), Unit(Unit) {}
|
||||
explicit DIETypeSignature(const DwarfTypeUnit &Unit) : Unit(&Unit) {}
|
||||
|
||||
// \brief Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *E) {
|
||||
return E->getType() == isTypeSignature;
|
||||
}
|
||||
|
||||
private:
|
||||
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const {
|
||||
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
||||
assert(Form == dwarf::DW_FORM_ref_sig8);
|
||||
return 8;
|
||||
}
|
||||
|
||||
#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
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIELoc - Represents an expression location.
|
||||
//
|
||||
class DIELoc : public DIEValue, public DIE {
|
||||
friend class DIEValue;
|
||||
|
||||
class DIELoc : public DIE {
|
||||
mutable unsigned Size; // Size in bytes excluding size header.
|
||||
|
||||
public:
|
||||
DIELoc() : DIEValue(isLoc), Size(0) {}
|
||||
DIELoc() : Size(0) {}
|
||||
|
||||
/// ComputeSize - Calculate the size of the location expression.
|
||||
///
|
||||
@ -485,27 +594,22 @@ class DIELoc : public DIEValue, public DIE {
|
||||
return dwarf::DW_FORM_block;
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *E) { return E->getType() == isLoc; }
|
||||
|
||||
private:
|
||||
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void printImpl(raw_ostream &O) const;
|
||||
void print(raw_ostream &O) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEBlock - Represents a block of values.
|
||||
//
|
||||
class DIEBlock : public DIEValue, public DIE {
|
||||
friend class DIEValue;
|
||||
|
||||
class DIEBlock : public DIE {
|
||||
mutable unsigned Size; // Size in bytes excluding size header.
|
||||
|
||||
public:
|
||||
DIEBlock() : DIEValue(isBlock), Size(0) {}
|
||||
DIEBlock() : Size(0) {}
|
||||
|
||||
/// ComputeSize - Calculate the size of the location expression.
|
||||
///
|
||||
@ -523,43 +627,11 @@ class DIEBlock : public DIEValue, public DIE {
|
||||
return dwarf::DW_FORM_block;
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEValue *E) { return E->getType() == isBlock; }
|
||||
|
||||
private:
|
||||
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void printImpl(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;
|
||||
void print(raw_ostream &O) const;
|
||||
#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
|
||||
/// MachineModuleInfo).
|
||||
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.
|
||||
|
@ -102,6 +102,10 @@ class LiveRangeEdit : private MachineRegisterInfo::Delegate {
|
||||
/// registers are created.
|
||||
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:
|
||||
/// Create a LiveRangeEdit for breaking down parent into smaller pieces.
|
||||
/// @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.
|
||||
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:
|
||||
explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign,
|
||||
bool RealignOpt)
|
||||
@ -627,16 +622,15 @@ class MachineFrameInfo {
|
||||
MachineBasicBlock *getRestorePoint() const { return Restore; }
|
||||
void setRestorePoint(MachineBasicBlock *NewRestore) { Restore = NewRestore; }
|
||||
|
||||
/// getPristineRegs - Return a set of physical registers that are pristine on
|
||||
/// entry to the MBB.
|
||||
/// Return a set of physical registers that are pristine.
|
||||
///
|
||||
/// 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
|
||||
/// been saved yet.
|
||||
/// but that must be preserved - they are callee saved registers that are not
|
||||
/// saved.
|
||||
///
|
||||
/// Before the PrologueEpilogueInserter has placed the CSR spill code, this
|
||||
/// 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
|
||||
/// stack objects. Implemented in MachineFunction.cpp
|
||||
|
@ -331,6 +331,11 @@ class MachineInstr : public ilist_node<MachineInstr> {
|
||||
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
|
||||
mmo_iterator memoperands_begin() const { return MemRefs; }
|
||||
mmo_iterator memoperands_end() const { return MemRefs + NumMemRefs; }
|
||||
@ -483,6 +488,13 @@ class MachineInstr : public ilist_node<MachineInstr> {
|
||||
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
|
||||
/// which must be filled by the code generator.
|
||||
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 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.
|
||||
///
|
||||
const TargetRegisterClass*
|
||||
@ -936,10 +948,10 @@ class MachineInstr : public ilist_node<MachineInstr> {
|
||||
/// the given \p CurRC.
|
||||
/// 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,
|
||||
/// 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.
|
||||
///
|
||||
/// 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
|
||||
/// exist.
|
||||
///
|
||||
@ -952,7 +964,7 @@ class MachineInstr : public ilist_node<MachineInstr> {
|
||||
/// \brief Applies the constraints (def/use) implied by the \p OpIdx operand
|
||||
/// 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
|
||||
/// does not exist.
|
||||
///
|
||||
|
@ -114,7 +114,7 @@ class MachineLoopInfo : public MachineFunctionPass {
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,11 @@
|
||||
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class FunctionPass;
|
||||
class MachineFunctionPass;
|
||||
class PassConfigImpl;
|
||||
class PassInfo;
|
||||
@ -374,6 +374,10 @@ namespace llvm {
|
||||
createMachineFunctionPrinterPass(raw_ostream &OS,
|
||||
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
|
||||
/// matching during instruction selection.
|
||||
FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr);
|
||||
@ -488,6 +492,10 @@ namespace llvm {
|
||||
/// MachineFunctionPrinterPass - This pass prints out MachineInstr's.
|
||||
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
|
||||
/// into tails of their predecessors.
|
||||
extern char &TailDuplicateID;
|
||||
@ -511,6 +519,8 @@ namespace llvm {
|
||||
/// IfConverter - This pass performs machine code if conversion.
|
||||
extern char &IfConverterID;
|
||||
|
||||
FunctionPass *createIfConverter(std::function<bool(const Function &)> Ftor);
|
||||
|
||||
/// MachineBlockPlacement - This pass places basic blocks based on branch
|
||||
/// probabilities.
|
||||
extern char &MachineBlockPlacementID;
|
||||
@ -605,6 +615,9 @@ namespace llvm {
|
||||
/// UnpackMachineBundles - This pass unpack machine instruction bundles.
|
||||
extern char &UnpackMachineBundlesID;
|
||||
|
||||
FunctionPass *
|
||||
createUnpackMachineBundles(std::function<bool(const Function &)> Ftor);
|
||||
|
||||
/// FinalizeMachineBundles - This pass finalize machine instruction
|
||||
/// bundles (created earlier, e.g. during pre-RA scheduling).
|
||||
extern char &FinalizeMachineBundlesID;
|
||||
|
@ -260,7 +260,7 @@ namespace llvm {
|
||||
#ifndef NDEBUG
|
||||
const SUnit *Addr = SUnits.empty() ? nullptr : &SUnits[0];
|
||||
#endif
|
||||
SUnits.push_back(SUnit(MI, (unsigned)SUnits.size()));
|
||||
SUnits.emplace_back(MI, (unsigned)SUnits.size());
|
||||
assert((Addr == nullptr || Addr == &SUnits[0]) &&
|
||||
"SUnits std::vector reallocated on the fly!");
|
||||
SUnits.back().OrigNode = &SUnits.back();
|
||||
|
@ -878,6 +878,10 @@ class SelectionDAG {
|
||||
/// Return an MDNodeSDNode which holds an MDNode.
|
||||
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.
|
||||
SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr,
|
||||
unsigned SrcAS, unsigned DestAS);
|
||||
|
@ -23,6 +23,7 @@ class BasicBlock;
|
||||
class Constant;
|
||||
class Function;
|
||||
class GlobalVariable;
|
||||
class InvokeInst;
|
||||
class IntrinsicInst;
|
||||
class LandingPadInst;
|
||||
class MCSymbol;
|
||||
@ -153,5 +154,11 @@ struct WinEHFuncInfo {
|
||||
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
|
||||
|
@ -141,8 +141,7 @@ class DIContext {
|
||||
/// on the fly.
|
||||
class LoadedObjectInfo {
|
||||
public:
|
||||
LoadedObjectInfo() {}
|
||||
virtual ~LoadedObjectInfo() {}
|
||||
virtual ~LoadedObjectInfo() = default;
|
||||
|
||||
/// Obtain the Load Address of a section by Name.
|
||||
///
|
||||
@ -170,7 +169,7 @@ class LoadedObjectInfo {
|
||||
/// Obtain a copy of this LoadedObjectInfo.
|
||||
///
|
||||
/// 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
|
||||
// (not including the total_length field itself).
|
||||
uint32_t TotalLength;
|
||||
uint64_t TotalLength;
|
||||
// Version identifier for the statement information format.
|
||||
uint16_t Version;
|
||||
// The number of bytes following the prologue_length field to the beginning
|
||||
// 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
|
||||
// program opcodes that alter the address register first multiply their
|
||||
// operands by this value.
|
||||
@ -63,14 +63,22 @@ class DWARFDebugLine {
|
||||
std::vector<const char*> IncludeDirectories;
|
||||
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.
|
||||
uint32_t getLength() const {
|
||||
return PrologueLength + sizeof(TotalLength) + sizeof(Version) +
|
||||
sizeof(PrologueLength);
|
||||
return PrologueLength + sizeofTotalLength() + sizeof(Version) +
|
||||
sizeofPrologueLength();
|
||||
}
|
||||
// Length of the line table data in bytes (not including the prologue).
|
||||
uint32_t getStatementTableLength() const {
|
||||
return TotalLength + sizeof(TotalLength) - getLength();
|
||||
return TotalLength + sizeofTotalLength() - getLength();
|
||||
}
|
||||
int32_t getMaxLineIncrementForSpecialOpcode() const {
|
||||
return LineBase + (int8_t)LineRange - 1;
|
||||
@ -163,6 +171,9 @@ class DWARFDebugLine {
|
||||
struct LineTable {
|
||||
LineTable();
|
||||
|
||||
// Represents an invalid row
|
||||
const uint32_t UnknownRowIndex = UINT32_MAX;
|
||||
|
||||
void appendRow(const DWARFDebugLine::Row &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,
|
||||
// or -1 if there is no such row.
|
||||
// or UnknownRowIndex if there is no such row.
|
||||
uint32_t lookupAddress(uint64_t address) const;
|
||||
|
||||
bool lookupAddressRange(uint64_t address, uint64_t size,
|
||||
@ -203,6 +214,10 @@ class DWARFDebugLine {
|
||||
typedef SequenceVector::const_iterator SequenceIter;
|
||||
RowVector Rows;
|
||||
SequenceVector Sequences;
|
||||
|
||||
private:
|
||||
uint32_t findRowInSeq(const DWARFDebugLine::Sequence &seq,
|
||||
uint64_t address) const;
|
||||
};
|
||||
|
||||
const LineTable *getLineTable(uint32_t offset) const;
|
||||
|
@ -390,8 +390,7 @@ class CompileOnDemandLayer {
|
||||
for (auto &F : *M) {
|
||||
if (F.isDeclaration())
|
||||
continue;
|
||||
Partitioning.push_back(std::vector<Function*>());
|
||||
Partitioning.back().push_back(&F);
|
||||
Partitioning.emplace_back(1, &F);
|
||||
}
|
||||
addLogicalModule(*LogicalDylibs.back(),
|
||||
std::shared_ptr<Module>(std::move(M)),
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H
|
||||
|
||||
#include "JITSymbolFlags.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Memory.h"
|
||||
#include "llvm/DebugInfo/DIContext.h"
|
||||
@ -62,8 +63,6 @@ class RuntimeDyld {
|
||||
unsigned EndIdx)
|
||||
: RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { }
|
||||
|
||||
virtual ~LoadedObjectInfo() = default;
|
||||
|
||||
virtual object::OwningBinary<object::ObjectFile>
|
||||
getObjectForDebug(const object::ObjectFile &Obj) const = 0;
|
||||
|
||||
@ -80,8 +79,8 @@ class RuntimeDyld {
|
||||
LoadedObjectInfoHelper(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
|
||||
unsigned EndIdx)
|
||||
: LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {}
|
||||
llvm::LoadedObjectInfo *clone() const override {
|
||||
return new Derived(static_cast<const Derived &>(*this));
|
||||
std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
|
||||
return llvm::make_unique<Derived>(static_cast<const Derived &>(*this));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -248,6 +248,13 @@ class InlineAsm : public Value {
|
||||
Constraint_R,
|
||||
Constraint_S,
|
||||
Constraint_T,
|
||||
Constraint_Um,
|
||||
Constraint_Un,
|
||||
Constraint_Uq,
|
||||
Constraint_Us,
|
||||
Constraint_Ut,
|
||||
Constraint_Uv,
|
||||
Constraint_Uy,
|
||||
Constraint_X,
|
||||
Constraint_Z,
|
||||
Constraint_ZC,
|
||||
|
@ -810,6 +810,7 @@ inline Type *checkGEPType(Type *Ty) {
|
||||
///
|
||||
class GetElementPtrInst : public Instruction {
|
||||
Type *SourceElementType;
|
||||
Type *ResultElementType;
|
||||
|
||||
GetElementPtrInst(const GetElementPtrInst &GEPI);
|
||||
void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr);
|
||||
@ -903,9 +904,12 @@ class GetElementPtrInst : public Instruction {
|
||||
Type *getSourceElementType() const { return SourceElementType; }
|
||||
|
||||
void setSourceElementType(Type *Ty) { SourceElementType = Ty; }
|
||||
void setResultElementType(Type *Ty) { ResultElementType = Ty; }
|
||||
|
||||
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.
|
||||
@ -1028,7 +1032,10 @@ GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr,
|
||||
: Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr,
|
||||
OperandTraits<GetElementPtrInst>::op_end(this) - Values,
|
||||
Values, InsertBefore),
|
||||
SourceElementType(PointeeType) {
|
||||
SourceElementType(PointeeType),
|
||||
ResultElementType(getIndexedType(PointeeType, IdxList)) {
|
||||
assert(ResultElementType ==
|
||||
cast<PointerType>(getType()->getScalarType())->getElementType());
|
||||
init(Ptr, IdxList, NameStr);
|
||||
}
|
||||
GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr,
|
||||
@ -1038,7 +1045,10 @@ GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr,
|
||||
: Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr,
|
||||
OperandTraits<GetElementPtrInst>::op_end(this) - Values,
|
||||
Values, InsertAtEnd),
|
||||
SourceElementType(PointeeType) {
|
||||
SourceElementType(PointeeType),
|
||||
ResultElementType(getIndexedType(PointeeType, IdxList)) {
|
||||
assert(ResultElementType ==
|
||||
cast<PointerType>(getType()->getScalarType())->getElementType());
|
||||
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],
|
||||
[llvm_i64_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_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],
|
||||
[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,
|
||||
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,
|
||||
llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
|
||||
|
@ -153,7 +153,7 @@ class MDBuilder {
|
||||
/// \brief Return metadata for a TBAA tag node with the given
|
||||
/// base type, access type and offset relative to the base type.
|
||||
MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType,
|
||||
uint64_t Offset);
|
||||
uint64_t Offset, bool IsConstant = false);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -69,9 +69,8 @@ class Value {
|
||||
Type *VTy;
|
||||
Use *UseList;
|
||||
|
||||
friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD.
|
||||
friend class ValueAsMetadata; // Allow access to IsUsedByMD.
|
||||
friend class ValueHandleBase;
|
||||
PointerIntPair<ValueName *, 1> NameAndIsUsedByMD;
|
||||
|
||||
const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast)
|
||||
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
|
||||
/// instances of Value have operands, 32-bit hosts aren't significantly
|
||||
/// affected.
|
||||
unsigned NumOperands;
|
||||
unsigned NumOperands : 30;
|
||||
|
||||
bool IsUsedByMD : 1;
|
||||
bool HasName : 1;
|
||||
|
||||
private:
|
||||
template <typename UseT> // UseT == 'Use' or 'const Use'
|
||||
@ -210,9 +212,9 @@ class Value {
|
||||
LLVMContext &getContext() const;
|
||||
|
||||
// \brief All values can potentially be named.
|
||||
bool hasName() const { return getValueName() != nullptr; }
|
||||
ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); }
|
||||
void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); }
|
||||
bool hasName() const { return HasName; }
|
||||
ValueName *getValueName() const;
|
||||
void setValueName(ValueName *VN);
|
||||
|
||||
private:
|
||||
void destroyValueName();
|
||||
@ -394,7 +396,7 @@ class Value {
|
||||
bool hasValueHandle() const { return HasValueHandle; }
|
||||
|
||||
/// \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.
|
||||
///
|
||||
|
@ -289,6 +289,7 @@ void initializeLoopVectorizePass(PassRegistry&);
|
||||
void initializeSLPVectorizerPass(PassRegistry&);
|
||||
void initializeBBVectorizePass(PassRegistry&);
|
||||
void initializeMachineFunctionPrinterPassPass(PassRegistry&);
|
||||
void initializeMIRPrintingPassPass(PassRegistry&);
|
||||
void initializeStackMapLivenessPass(PassRegistry&);
|
||||
void initializeMachineCombinerPass(PassRegistry &);
|
||||
void initializeLoadCombinePass(PassRegistry&);
|
||||
|
@ -82,7 +82,7 @@ struct LTOCodeGenerator {
|
||||
void setShouldInternalize(bool Value) { ShouldInternalize = 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
|
||||
// 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
|
||||
// caller. This function should delete intermediate object file once its content
|
||||
// is brought to memory. Return NULL if the compilation was not successful.
|
||||
const void *compile(size_t *length,
|
||||
bool disableInline,
|
||||
bool disableGVNLoadPRE,
|
||||
bool disableVectorization,
|
||||
std::string &errMsg);
|
||||
std::unique_ptr<MemoryBuffer> compile(bool disableInline,
|
||||
bool disableGVNLoadPRE,
|
||||
bool disableVectorization,
|
||||
std::string &errMsg);
|
||||
|
||||
// Optimizes the merged module. Returns true on success.
|
||||
bool optimize(bool disableInline,
|
||||
@ -132,7 +131,7 @@ struct LTOCodeGenerator {
|
||||
// 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
|
||||
// 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 *);
|
||||
|
||||
@ -166,7 +165,6 @@ struct LTOCodeGenerator {
|
||||
lto_codegen_model CodeModel = LTO_CODEGEN_PIC_MODEL_DEFAULT;
|
||||
StringSet MustPreserveSymbols;
|
||||
StringSet AsmUndefinedRefs;
|
||||
std::unique_ptr<MemoryBuffer> NativeObjectFile;
|
||||
std::vector<char *> CodegenOptions;
|
||||
std::string MCpu;
|
||||
std::string MAttr;
|
||||
|
@ -97,6 +97,12 @@ class MCAsmBackend {
|
||||
|
||||
/// Target specific predicate for whether a given fixup requires the
|
||||
/// 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,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const = 0;
|
||||
|
@ -155,6 +155,10 @@ class MCAsmInfo {
|
||||
/// Defaults to false.
|
||||
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
|
||||
/// ".data_region/.end_data_region" directives. If false, use "$d/$a" labels
|
||||
/// instead.
|
||||
@ -406,6 +410,10 @@ class MCAsmInfo {
|
||||
unsigned Encoding,
|
||||
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 {
|
||||
return SunStyleELFSectionSwitchSyntax;
|
||||
}
|
||||
@ -456,6 +464,7 @@ class MCAsmInfo {
|
||||
const char *getCode64Directive() const { return Code64Directive; }
|
||||
unsigned getAssemblerDialect() const { return AssemblerDialect; }
|
||||
bool doesAllowAtInName() const { return AllowAtInName; }
|
||||
bool supportsNameQuoting() const { return SupportsQuotedNames; }
|
||||
bool doesSupportDataRegionDirectives() const {
|
||||
return UseDataRegionDirectives;
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ class MCAssembler;
|
||||
class MCFragment;
|
||||
class MCSection;
|
||||
class MCSymbol;
|
||||
class MCSymbolData;
|
||||
|
||||
/// 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/DenseSet.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
@ -24,7 +23,6 @@
|
||||
#include "llvm/MC/MCLinkerOptimizationHint.h"
|
||||
#include "llvm/MC/MCSection.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <algorithm>
|
||||
@ -60,7 +58,8 @@ class MCFragment : public ilist_node<MCFragment> {
|
||||
FT_Org,
|
||||
FT_Dwarf,
|
||||
FT_DwarfFrame,
|
||||
FT_LEB
|
||||
FT_LEB,
|
||||
FT_SafeSEH
|
||||
};
|
||||
|
||||
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.
|
||||
struct IndirectSymbolData {
|
||||
MCSymbol *Symbol;
|
||||
@ -551,7 +572,7 @@ class MCAssembler {
|
||||
friend class MCAsmLayout;
|
||||
|
||||
public:
|
||||
typedef SetVector<MCSection *> SectionListType;
|
||||
typedef std::vector<MCSection *> SectionListType;
|
||||
typedef std::vector<const MCSymbol *> SymbolDataListType;
|
||||
|
||||
typedef pointee_iterator<SectionListType::const_iterator> const_iterator;
|
||||
@ -564,9 +585,6 @@ class MCAssembler {
|
||||
typedef iterator_range<symbol_iterator> 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
|
||||
const_indirect_symbol_iterator;
|
||||
typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
|
||||
@ -613,7 +631,7 @@ class MCAssembler {
|
||||
std::vector<std::vector<std::string>> LinkerOptions;
|
||||
|
||||
/// List of declared file names
|
||||
FileNameVectorType FileNames;
|
||||
std::vector<std::string> FileNames;
|
||||
|
||||
/// The set of function symbols for which a .thumb_func directive has
|
||||
/// been seen.
|
||||
@ -883,39 +901,21 @@ class MCAssembler {
|
||||
/// \name Backend Data Access
|
||||
/// @{
|
||||
|
||||
bool registerSection(MCSection &Section) { return Sections.insert(&Section); }
|
||||
|
||||
bool hasSymbolData(const MCSymbol &Symbol) const { return Symbol.hasData(); }
|
||||
|
||||
MCSymbolData &getSymbolData(const MCSymbol &Symbol) {
|
||||
return const_cast<MCSymbolData &>(
|
||||
static_cast<const MCAssembler &>(*this).getSymbolData(Symbol));
|
||||
bool registerSection(MCSection &Section) {
|
||||
if (Section.isRegistered())
|
||||
return false;
|
||||
Sections.push_back(&Section);
|
||||
Section.setIsRegistered(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
const MCSymbolData &getSymbolData(const MCSymbol &Symbol) const {
|
||||
return Symbol.getData();
|
||||
}
|
||||
void registerSymbol(const MCSymbol &Symbol, bool *Created = nullptr);
|
||||
|
||||
MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol,
|
||||
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(); }
|
||||
ArrayRef<std::string> getFileNames() { return FileNames; }
|
||||
|
||||
void addFileName(StringRef FileName) {
|
||||
if (std::find(file_names_begin(), file_names_end(), FileName) ==
|
||||
file_names_end())
|
||||
if (std::find(FileNames.begin(), FileNames.end(), FileName) ==
|
||||
FileNames.end())
|
||||
FileNames.push_back(FileName);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ namespace llvm {
|
||||
class MCExpr;
|
||||
class MCSection;
|
||||
class MCSymbol;
|
||||
class MCSymbolELF;
|
||||
class MCLabel;
|
||||
struct MCDwarfFile;
|
||||
class MCDwarfLoc;
|
||||
@ -75,7 +76,7 @@ namespace llvm {
|
||||
|
||||
/// ELF sections can have a corresponding symbol. This maps one to the
|
||||
/// 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.
|
||||
/// For example, in the assembly
|
||||
@ -205,7 +206,10 @@ namespace llvm {
|
||||
/// Do automatic reset in destructor
|
||||
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,
|
||||
unsigned Instance);
|
||||
@ -263,7 +267,7 @@ namespace llvm {
|
||||
/// \param Name - The symbol name, which must be unique across all symbols.
|
||||
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
|
||||
/// variable after codegen.
|
||||
@ -340,18 +344,18 @@ namespace llvm {
|
||||
|
||||
MCSectionELF *getELFSection(StringRef Section, unsigned Type,
|
||||
unsigned Flags, unsigned EntrySize,
|
||||
const MCSymbol *Group, unsigned UniqueID,
|
||||
const MCSymbolELF *Group, unsigned UniqueID,
|
||||
const char *BeginSymName,
|
||||
const MCSectionELF *Associated);
|
||||
|
||||
MCSectionELF *createELFRelSection(StringRef Name, unsigned Type,
|
||||
unsigned Flags, unsigned EntrySize,
|
||||
const MCSymbol *Group,
|
||||
const MCSymbolELF *Group,
|
||||
const MCSectionELF *Associated);
|
||||
|
||||
void renameELFSection(MCSectionELF *Section, StringRef Name);
|
||||
|
||||
MCSectionELF *createELFGroupSection(const MCSymbol *Group);
|
||||
MCSectionELF *createELFGroupSection(const MCSymbolELF *Group);
|
||||
|
||||
MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
|
||||
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 MCObjectWriter;
|
||||
class MCSymbol;
|
||||
class MCSymbolData;
|
||||
class MCSymbolELF;
|
||||
class MCValue;
|
||||
class raw_pwrite_stream;
|
||||
|
||||
struct ELFRelocationEntry {
|
||||
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.
|
||||
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)
|
||||
: Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {}
|
||||
};
|
||||
@ -69,7 +69,7 @@ class MCELFObjectTargetWriter {
|
||||
virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
|
||||
bool IsPCRel) const = 0;
|
||||
|
||||
virtual bool needsRelocateWithSymbol(const MCSymbolData &SD,
|
||||
virtual bool needsRelocateWithSymbol(const MCSymbol &Sym,
|
||||
unsigned Type) const;
|
||||
|
||||
virtual void sortRelocs(const MCAssembler &Asm,
|
||||
|
@ -23,8 +23,6 @@ class MCAssembler;
|
||||
class MCCodeEmitter;
|
||||
class MCExpr;
|
||||
class MCInst;
|
||||
class MCSymbol;
|
||||
class MCSymbolData;
|
||||
class raw_ostream;
|
||||
|
||||
class MCELFStreamer : public MCObjectStreamer {
|
||||
@ -39,7 +37,6 @@ class MCELFStreamer : public MCObjectStreamer {
|
||||
void reset() override {
|
||||
SeenIdent = false;
|
||||
LocalCommons.clear();
|
||||
BindingExplicitlySet.clear();
|
||||
BundleGroups.clear();
|
||||
MCObjectStreamer::reset();
|
||||
}
|
||||
@ -62,7 +59,7 @@ class MCELFStreamer : public MCObjectStreamer {
|
||||
void EmitCOFFSymbolType(int Type) 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,
|
||||
unsigned ByteAlignment) override;
|
||||
@ -108,8 +105,6 @@ class MCELFStreamer : public MCObjectStreamer {
|
||||
|
||||
std::vector<LocalCommon> LocalCommons;
|
||||
|
||||
SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet;
|
||||
|
||||
/// BundleGroups - The stack of fragments holding the bundle-locked
|
||||
/// instructions.
|
||||
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;
|
||||
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 SectionAddrMap *Addrs) const;
|
||||
|
||||
@ -57,7 +57,7 @@ class MCExpr {
|
||||
protected:
|
||||
explicit MCExpr(ExprKind Kind) : Kind(Kind) {}
|
||||
|
||||
bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
||||
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
||||
const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup,
|
||||
const SectionAddrMap *Addrs, bool InSet) const;
|
||||
@ -72,7 +72,7 @@ class MCExpr {
|
||||
/// \name Utility Methods
|
||||
/// @{
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
|
||||
void dump() const;
|
||||
|
||||
/// @}
|
||||
@ -86,11 +86,11 @@ class MCExpr {
|
||||
/// values. If not given, then only non-symbolic expressions will be
|
||||
/// evaluated.
|
||||
/// \return - True on success.
|
||||
bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout,
|
||||
bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout,
|
||||
const SectionAddrMap &Addrs) const;
|
||||
bool EvaluateAsAbsolute(int64_t &Res) 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;
|
||||
bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const;
|
||||
bool evaluateAsAbsolute(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 Fixup - The Fixup object if available.
|
||||
/// \return - True on success.
|
||||
bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout,
|
||||
bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const;
|
||||
|
||||
/// \brief Try to evaluate the expression to the form (a - b + constant) where
|
||||
/// 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.
|
||||
bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const;
|
||||
|
||||
@ -115,13 +115,13 @@ class MCExpr {
|
||||
/// currently defined as the absolute section for constants, or
|
||||
/// otherwise the section associated with the first defined symbol in the
|
||||
/// expression.
|
||||
MCSection *FindAssociatedSection() const;
|
||||
MCSection *findAssociatedSection() const;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) {
|
||||
E.print(OS);
|
||||
E.print(OS, nullptr);
|
||||
return OS;
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ class MCConstantExpr : public MCExpr {
|
||||
/// \name Construction
|
||||
/// @{
|
||||
|
||||
static const MCConstantExpr *Create(int64_t Value, MCContext &Ctx);
|
||||
static const MCConstantExpr *create(int64_t Value, MCContext &Ctx);
|
||||
|
||||
/// @}
|
||||
/// \name Accessors
|
||||
@ -312,13 +312,13 @@ class MCSymbolRefExpr : public MCExpr {
|
||||
/// \name Construction
|
||||
/// @{
|
||||
|
||||
static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, MCContext &Ctx) {
|
||||
return MCSymbolRefExpr::Create(Symbol, VK_None, Ctx);
|
||||
static const MCSymbolRefExpr *create(const MCSymbol *Symbol, MCContext &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);
|
||||
static const MCSymbolRefExpr *Create(StringRef Name, VariantKind Kind,
|
||||
static const MCSymbolRefExpr *create(StringRef Name, VariantKind Kind,
|
||||
MCContext &Ctx);
|
||||
|
||||
/// @}
|
||||
@ -369,19 +369,19 @@ class MCUnaryExpr : public MCExpr {
|
||||
/// \name Construction
|
||||
/// @{
|
||||
|
||||
static const MCUnaryExpr *Create(Opcode Op, const MCExpr *Expr,
|
||||
static const MCUnaryExpr *create(Opcode Op, const MCExpr *Expr,
|
||||
MCContext &Ctx);
|
||||
static const MCUnaryExpr *CreateLNot(const MCExpr *Expr, MCContext &Ctx) {
|
||||
return Create(LNot, Expr, Ctx);
|
||||
static const MCUnaryExpr *createLNot(const MCExpr *Expr, MCContext &Ctx) {
|
||||
return create(LNot, Expr, Ctx);
|
||||
}
|
||||
static const MCUnaryExpr *CreateMinus(const MCExpr *Expr, MCContext &Ctx) {
|
||||
return Create(Minus, Expr, Ctx);
|
||||
static const MCUnaryExpr *createMinus(const MCExpr *Expr, MCContext &Ctx) {
|
||||
return create(Minus, Expr, Ctx);
|
||||
}
|
||||
static const MCUnaryExpr *CreateNot(const MCExpr *Expr, MCContext &Ctx) {
|
||||
return Create(Not, Expr, Ctx);
|
||||
static const MCUnaryExpr *createNot(const MCExpr *Expr, MCContext &Ctx) {
|
||||
return create(Not, Expr, Ctx);
|
||||
}
|
||||
static const MCUnaryExpr *CreatePlus(const MCExpr *Expr, MCContext &Ctx) {
|
||||
return Create(Plus, Expr, Ctx);
|
||||
static const MCUnaryExpr *createPlus(const MCExpr *Expr, MCContext &Ctx) {
|
||||
return create(Plus, Expr, Ctx);
|
||||
}
|
||||
|
||||
/// @}
|
||||
@ -441,83 +441,83 @@ class MCBinaryExpr : public MCExpr {
|
||||
/// \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);
|
||||
static const MCBinaryExpr *CreateAdd(const MCExpr *LHS, const MCExpr *RHS,
|
||||
static const MCBinaryExpr *createAdd(const MCExpr *LHS, const MCExpr *RHS,
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
return Create(Xor, LHS, RHS, Ctx);
|
||||
return create(Xor, LHS, RHS, Ctx);
|
||||
}
|
||||
|
||||
/// @}
|
||||
@ -551,13 +551,12 @@ class MCTargetExpr : public MCExpr {
|
||||
MCTargetExpr() : MCExpr(Target) {}
|
||||
virtual ~MCTargetExpr() {}
|
||||
public:
|
||||
|
||||
virtual void PrintImpl(raw_ostream &OS) const = 0;
|
||||
virtual bool EvaluateAsRelocatableImpl(MCValue &Res,
|
||||
virtual void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const = 0;
|
||||
virtual bool evaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) 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;
|
||||
|
||||
|
@ -32,12 +32,12 @@ class MCInst;
|
||||
/// This is a simple discriminated union.
|
||||
class MCOperand {
|
||||
enum MachineOperandType : unsigned char {
|
||||
kInvalid, ///< Uninitialized.
|
||||
kRegister, ///< Register operand.
|
||||
kImmediate, ///< Immediate operand.
|
||||
kFPImmediate, ///< Floating-point immediate operand.
|
||||
kExpr, ///< Relocatable immediate operand.
|
||||
kInst ///< Sub-instruction operand.
|
||||
kInvalid, ///< Uninitialized.
|
||||
kRegister, ///< Register operand.
|
||||
kImmediate, ///< Immediate operand.
|
||||
kFPImmediate, ///< Floating-point immediate operand.
|
||||
kExpr, ///< Relocatable immediate operand.
|
||||
kInst ///< Sub-instruction operand.
|
||||
};
|
||||
MachineOperandType Kind;
|
||||
|
||||
@ -48,8 +48,8 @@ class MCOperand {
|
||||
const MCExpr *ExprVal;
|
||||
const MCInst *InstVal;
|
||||
};
|
||||
public:
|
||||
|
||||
public:
|
||||
MCOperand() : Kind(kInvalid), FPImmVal(0.0) {}
|
||||
|
||||
bool isValid() const { return Kind != kInvalid; }
|
||||
@ -151,6 +151,7 @@ class MCInst {
|
||||
unsigned Opcode;
|
||||
SMLoc Loc;
|
||||
SmallVector<MCOperand, 8> Operands;
|
||||
|
||||
public:
|
||||
MCInst() : Opcode(0) {}
|
||||
|
||||
@ -164,18 +165,16 @@ class MCInst {
|
||||
MCOperand &getOperand(unsigned i) { return Operands[i]; }
|
||||
unsigned getNumOperands() const { return Operands.size(); }
|
||||
|
||||
void addOperand(const MCOperand &Op) {
|
||||
Operands.push_back(Op);
|
||||
}
|
||||
|
||||
void clear() { Operands.clear(); }
|
||||
size_t size() const { return Operands.size(); }
|
||||
void addOperand(const MCOperand &Op) { Operands.push_back(Op); }
|
||||
|
||||
typedef SmallVectorImpl<MCOperand>::iterator 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(); }
|
||||
const_iterator begin() const { return Operands.begin(); }
|
||||
iterator end() { return Operands.end(); }
|
||||
iterator end() { return Operands.end(); }
|
||||
const_iterator end() const { return Operands.end(); }
|
||||
iterator insert(iterator I, const MCOperand &Op) {
|
||||
return Operands.insert(I, Op);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef LLVM_MC_MCINSTPRINTER_H
|
||||
#define LLVM_MC_MCINSTPRINTER_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
|
||||
@ -22,11 +23,14 @@ class MCRegisterInfo;
|
||||
class MCSubtargetInfo;
|
||||
class StringRef;
|
||||
|
||||
/// Convert `Bytes' to a hex string and output to `OS'
|
||||
void dumpBytes(ArrayRef<uint8_t> Bytes, raw_ostream &OS);
|
||||
|
||||
namespace HexStyle {
|
||||
enum Style {
|
||||
C, ///< 0xff
|
||||
Asm ///< 0ffh
|
||||
};
|
||||
enum Style {
|
||||
C, ///< 0xff
|
||||
Asm ///< 0ffh
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief This is an instance of a target assembly language printer that
|
||||
@ -52,12 +56,12 @@ class MCInstPrinter {
|
||||
|
||||
/// Utility function for printing annotations.
|
||||
void printAnnotation(raw_ostream &OS, StringRef Annot);
|
||||
|
||||
public:
|
||||
MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii,
|
||||
const MCRegisterInfo &mri)
|
||||
: CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri),
|
||||
UseMarkup(0), PrintImmHex(0),
|
||||
PrintHexStyle(HexStyle::C) {}
|
||||
: CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri), UseMarkup(0),
|
||||
PrintImmHex(0), PrintHexStyle(HexStyle::C) {}
|
||||
|
||||
virtual ~MCInstPrinter();
|
||||
|
||||
@ -65,8 +69,8 @@ class MCInstPrinter {
|
||||
void setCommentStream(raw_ostream &OS) { CommentStream = &OS; }
|
||||
|
||||
/// \brief Print the specified MCInst to the specified raw_ostream.
|
||||
virtual void printInst(const MCInst *MI, raw_ostream &OS,
|
||||
StringRef Annot, const MCSubtargetInfo &STI) = 0;
|
||||
virtual void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot,
|
||||
const MCSubtargetInfo &STI) = 0;
|
||||
|
||||
/// \brief Return the name of the specified opcode enum (e.g. "MOV32ri") or
|
||||
/// empty if we can't resolve it.
|
||||
@ -85,8 +89,8 @@ class MCInstPrinter {
|
||||
bool getPrintImmHex() const { return PrintImmHex; }
|
||||
void setPrintImmHex(bool Value) { PrintImmHex = Value; }
|
||||
|
||||
HexStyle::Style getPrintHexStyleHex() const { return PrintHexStyle; }
|
||||
void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; }
|
||||
HexStyle::Style getPrintHexStyle() const { return PrintHexStyle; }
|
||||
void setPrintHexStyle(HexStyle::Style Value) { PrintHexStyle = Value; }
|
||||
|
||||
/// Utility function to print immediates in decimal or hex.
|
||||
format_object<int64_t> formatImm(int64_t Value) const {
|
||||
|
@ -125,7 +125,8 @@ enum Flag {
|
||||
ExtraDefRegAllocReq,
|
||||
RegSequence,
|
||||
ExtractSubreg,
|
||||
InsertSubreg
|
||||
InsertSubreg,
|
||||
Convergent
|
||||
};
|
||||
}
|
||||
|
||||
@ -138,10 +139,10 @@ class MCInstrDesc {
|
||||
public:
|
||||
unsigned short Opcode; // The opcode number
|
||||
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 Size; // Number of bytes in encoding.
|
||||
unsigned Flags; // Flags identifying machine instr class
|
||||
uint64_t Flags; // Flags identifying machine instr class
|
||||
uint64_t TSFlags; // Target Specific Flag values
|
||||
const uint16_t *ImplicitUses; // Registers implicitly read by this instr
|
||||
const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr
|
||||
@ -331,6 +332,13 @@ class MCInstrDesc {
|
||||
/// override accordingly.
|
||||
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
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -17,41 +17,41 @@
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCContext;
|
||||
class raw_ostream;
|
||||
class MCContext;
|
||||
class raw_ostream;
|
||||
|
||||
/// \brief Instances of this class represent a label name in the MC file,
|
||||
/// and MCLabel are created and uniqued by the MCContext class. MCLabel
|
||||
/// should only be constructed for valid instances in the object file.
|
||||
class MCLabel {
|
||||
// \brief The instance number of this Directional Local Label.
|
||||
unsigned Instance;
|
||||
/// \brief Instances of this class represent a label name in the MC file,
|
||||
/// and MCLabel are created and uniqued by the MCContext class. MCLabel
|
||||
/// should only be constructed for valid instances in the object file.
|
||||
class MCLabel {
|
||||
// \brief The instance number of this Directional Local Label.
|
||||
unsigned Instance;
|
||||
|
||||
private: // MCContext creates and uniques these.
|
||||
friend class MCContext;
|
||||
MCLabel(unsigned instance)
|
||||
: Instance(instance) {}
|
||||
private: // MCContext creates and uniques these.
|
||||
friend class MCContext;
|
||||
MCLabel(unsigned instance) : Instance(instance) {}
|
||||
|
||||
MCLabel(const MCLabel&) = delete;
|
||||
void operator=(const MCLabel&) = delete;
|
||||
public:
|
||||
/// \brief Get the current instance of this Directional Local Label.
|
||||
unsigned getInstance() const { return Instance; }
|
||||
MCLabel(const MCLabel &) = delete;
|
||||
void operator=(const MCLabel &) = delete;
|
||||
|
||||
/// \brief Increment the current instance of this Directional Local Label.
|
||||
unsigned incInstance() { return ++Instance; }
|
||||
public:
|
||||
/// \brief Get the current instance of this Directional Local Label.
|
||||
unsigned getInstance() const { return Instance; }
|
||||
|
||||
/// \brief Print the value to the stream \p OS.
|
||||
void print(raw_ostream &OS) const;
|
||||
/// \brief Increment the current instance of this Directional Local Label.
|
||||
unsigned incInstance() { return ++Instance; }
|
||||
|
||||
/// \brief Print the value to stderr.
|
||||
void dump() const;
|
||||
};
|
||||
/// \brief Print the value to the stream \p OS.
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const MCLabel &Label) {
|
||||
Label.print(OS);
|
||||
return OS;
|
||||
}
|
||||
/// \brief Print the value to stderr.
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const MCLabel &Label) {
|
||||
Label.print(OS);
|
||||
return OS;
|
||||
}
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -106,7 +106,7 @@ class MCLOHDirective {
|
||||
/// Emit this directive in \p OutStream using the information available
|
||||
/// in the given \p ObjWriter and \p Layout to get the address of the
|
||||
/// 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;
|
||||
|
||||
public:
|
||||
@ -123,9 +123,9 @@ class MCLOHDirective {
|
||||
|
||||
/// Emit this directive as:
|
||||
/// <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();
|
||||
Emit_impl(OutStream, ObjWriter, Layout);
|
||||
emit_impl(OutStream, ObjWriter, Layout);
|
||||
}
|
||||
|
||||
/// Get the size in bytes of this directive if emitted in \p ObjWriter with
|
||||
@ -145,7 +145,7 @@ class MCLOHDirective {
|
||||
};
|
||||
|
||||
raw_counting_ostream OutStream;
|
||||
Emit_impl(OutStream, ObjWriter, Layout);
|
||||
emit_impl(OutStream, ObjWriter, Layout);
|
||||
return OutStream.tell();
|
||||
}
|
||||
};
|
||||
@ -184,10 +184,10 @@ class MCLOHContainer {
|
||||
}
|
||||
|
||||
/// Emit all Linker Optimization Hint in one big table.
|
||||
/// Each line of the table is emitted by LOHDirective::Emit.
|
||||
void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
|
||||
/// Each line of the table is emitted by LOHDirective::emit.
|
||||
void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
|
||||
for (const MCLOHDirective &D : Directives)
|
||||
D.Emit(ObjWriter, Layout);
|
||||
D.emit(ObjWriter, Layout);
|
||||
}
|
||||
|
||||
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 uint32_t CPUType;
|
||||
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;
|
||||
|
||||
protected:
|
||||
MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_,
|
||||
uint32_t CPUSubtype_,
|
||||
bool UseAggressiveSymbolFolding_ = false);
|
||||
uint32_t CPUSubtype_);
|
||||
|
||||
void setLocalDifferenceRelocationType(unsigned Type) {
|
||||
LocalDifference_RIT = Type;
|
||||
@ -47,7 +43,7 @@ class MCMachObjectTargetWriter {
|
||||
/// \name Lifetime Management
|
||||
/// @{
|
||||
|
||||
virtual void reset() {};
|
||||
virtual void reset() {}
|
||||
|
||||
/// @}
|
||||
|
||||
@ -55,7 +51,6 @@ class MCMachObjectTargetWriter {
|
||||
/// @{
|
||||
|
||||
bool is64Bit() const { return Is64Bit; }
|
||||
bool useAggressiveSymbolFolding() const { return UseAggressiveSymbolFolding; }
|
||||
uint32_t getCPUType() const { return CPUType; }
|
||||
uint32_t getCPUSubtype() const { return CPUSubtype; }
|
||||
unsigned getLocalDifferenceRelocationType() const {
|
||||
@ -67,7 +62,7 @@ class MCMachObjectTargetWriter {
|
||||
/// \name API
|
||||
/// @{
|
||||
|
||||
virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
|
||||
virtual void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
@ -77,8 +72,7 @@ class MCMachObjectTargetWriter {
|
||||
};
|
||||
|
||||
class MachObjectWriter : public MCObjectWriter {
|
||||
/// MachSymbolData - Helper struct for containing some precomputed information
|
||||
/// on symbols.
|
||||
/// Helper struct for containing some precomputed information on symbols.
|
||||
struct MachSymbolData {
|
||||
const MCSymbol *Symbol;
|
||||
uint64_t StringIndex;
|
||||
@ -104,6 +98,8 @@ class MachObjectWriter : public MCObjectWriter {
|
||||
llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
|
||||
llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase;
|
||||
|
||||
SectionAddrMap SectionAddress;
|
||||
|
||||
/// @}
|
||||
/// \name Symbol Table Data
|
||||
/// @{
|
||||
@ -136,8 +132,6 @@ class MachObjectWriter : public MCObjectWriter {
|
||||
|
||||
bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
|
||||
|
||||
SectionAddrMap SectionAddress;
|
||||
|
||||
SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
|
||||
|
||||
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);
|
||||
|
||||
/// WriteSegmentLoadCommand - Write a segment load command.
|
||||
/// Write a segment load command.
|
||||
///
|
||||
/// \param NumSections The number of sections in this segment.
|
||||
/// \param SectionDataSize The total size of the sections.
|
||||
void WriteSegmentLoadCommand(unsigned NumSections,
|
||||
uint64_t VMSize,
|
||||
void writeSegmentLoadCommand(unsigned NumSections, uint64_t VMSize,
|
||||
uint64_t SectionDataStartOffset,
|
||||
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,
|
||||
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 StringTableSize);
|
||||
|
||||
void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
|
||||
uint32_t NumLocalSymbols,
|
||||
uint32_t FirstExternalSymbol,
|
||||
uint32_t NumExternalSymbols,
|
||||
uint32_t FirstUndefinedSymbol,
|
||||
uint32_t NumUndefinedSymbols,
|
||||
uint32_t IndirectSymbolOffset,
|
||||
uint32_t NumIndirectSymbols);
|
||||
void writeDysymtabLoadCommand(
|
||||
uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols,
|
||||
uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols,
|
||||
uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols,
|
||||
uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols);
|
||||
|
||||
void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
|
||||
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);
|
||||
|
||||
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
|
||||
// want to implement a separate computation which evaluates the relocation
|
||||
@ -226,29 +216,25 @@ class MachObjectWriter : public MCObjectWriter {
|
||||
Relocations[Sec].push_back(P);
|
||||
}
|
||||
|
||||
void RecordScatteredRelocation(const MCAssembler &Asm,
|
||||
void recordScatteredRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
unsigned Log2Size,
|
||||
uint64_t &FixedValue);
|
||||
unsigned Log2Size, uint64_t &FixedValue);
|
||||
|
||||
void RecordTLVPRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue);
|
||||
void recordTLVPRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment, 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,
|
||||
MCValue Target, bool &IsPCRel,
|
||||
uint64_t &FixedValue) override;
|
||||
|
||||
void BindIndirectSymbols(MCAssembler &Asm);
|
||||
void bindIndirectSymbols(MCAssembler &Asm);
|
||||
|
||||
/// ComputeSymbolTable - Compute the symbol table data
|
||||
///
|
||||
void ComputeSymbolTable(MCAssembler &Asm,
|
||||
/// Compute the symbol table data.
|
||||
void computeSymbolTable(MCAssembler &Asm,
|
||||
std::vector<MachSymbolData> &LocalSymbolData,
|
||||
std::vector<MachSymbolData> &ExternalSymbolData,
|
||||
std::vector<MachSymbolData> &UndefinedSymbolData);
|
||||
@ -256,19 +242,18 @@ class MachObjectWriter : public MCObjectWriter {
|
||||
void computeSectionAddresses(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout);
|
||||
|
||||
void ExecutePostLayoutBinding(MCAssembler &Asm,
|
||||
void executePostLayoutBinding(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) override;
|
||||
|
||||
bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
const MCSymbol &SymA,
|
||||
const MCFragment &FB, bool InSet,
|
||||
bool IsPCRel) const override;
|
||||
|
||||
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
|
||||
void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
|
||||
};
|
||||
|
||||
|
||||
/// \brief Construct a new Mach-O writer instance.
|
||||
/// Construct a new Mach-O writer instance.
|
||||
///
|
||||
/// This routine takes ownership of the target writer subclass.
|
||||
///
|
||||
|
@ -18,28 +18,25 @@
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCContext;
|
||||
class MCSection;
|
||||
class StringRef;
|
||||
class MCContext;
|
||||
class MCSection;
|
||||
class StringRef;
|
||||
|
||||
class MCObjectFileInfo {
|
||||
protected:
|
||||
/// CommDirectiveSupportsAlignment - True if .comm supports alignment. This
|
||||
/// is a hack for as long as we support 10.4 Tiger, whose assembler doesn't
|
||||
/// support alignment on comm.
|
||||
/// True if .comm supports alignment. This is a hack for as long as we
|
||||
/// support 10.4 Tiger, whose assembler doesn't support alignment on comm.
|
||||
bool CommDirectiveSupportsAlignment;
|
||||
|
||||
/// SupportsWeakEmptyEHFrame - True if target object file supports a
|
||||
/// weak_definition of constant 0 for an omitted EH frame.
|
||||
/// True if target object file supports a weak_definition of constant 0 for an
|
||||
/// omitted EH frame.
|
||||
bool SupportsWeakOmittedEHFrame;
|
||||
|
||||
/// SupportsCompactUnwindWithoutEHFrame - True if the target object file
|
||||
/// supports emitting a compact unwind section without an associated EH frame
|
||||
/// section.
|
||||
/// True if the target object file supports emitting a compact unwind section
|
||||
/// without an associated EH frame section.
|
||||
bool SupportsCompactUnwindWithoutEHFrame;
|
||||
|
||||
/// PersonalityEncoding, LSDAEncoding, TTypeEncoding - Some encoding values
|
||||
/// for EH.
|
||||
/// Some encoding values for EH.
|
||||
unsigned PersonalityEncoding;
|
||||
unsigned LSDAEncoding;
|
||||
unsigned FDECFIEncoding;
|
||||
@ -49,16 +46,13 @@ class MCObjectFileInfo {
|
||||
unsigned EHSectionType;
|
||||
unsigned EHSectionFlags;
|
||||
|
||||
/// CompactUnwindDwarfEHFrameOnly - Compact unwind encoding indicating that we
|
||||
/// should emit only an EH frame.
|
||||
/// Compact unwind encoding indicating that we should emit only an EH frame.
|
||||
unsigned CompactUnwindDwarfEHFrameOnly;
|
||||
|
||||
/// Section directive for standard text.
|
||||
///
|
||||
MCSection *TextSection;
|
||||
|
||||
/// Section directive for standard data.
|
||||
///
|
||||
MCSection *DataSection;
|
||||
|
||||
/// Section that is default initialized to zero.
|
||||
@ -101,7 +95,7 @@ class MCObjectFileInfo {
|
||||
// can be enabled by a compiler flag.
|
||||
MCSection *DwarfPubNamesSection;
|
||||
|
||||
// DWARF5 Experimental Debug Info Sections
|
||||
/// DWARF5 Experimental Debug Info Sections
|
||||
/// DwarfAccelNamesSection, DwarfAccelObjCSection,
|
||||
/// DwarfAccelNamespaceSection, DwarfAccelTypesSection -
|
||||
/// If we use the DWARF accelerated hash tables then we want to emit these
|
||||
@ -111,7 +105,7 @@ class MCObjectFileInfo {
|
||||
MCSection *DwarfAccelNamespaceSection;
|
||||
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 *DwarfTypesDWOSection;
|
||||
MCSection *DwarfAbbrevDWOSection;
|
||||
@ -121,32 +115,36 @@ class MCObjectFileInfo {
|
||||
MCSection *DwarfStrOffDWOSection;
|
||||
MCSection *DwarfAddrSection;
|
||||
|
||||
/// Sections for newer gnu pubnames and pubtypes.
|
||||
/// Section for newer gnu pubnames.
|
||||
MCSection *DwarfGnuPubNamesSection;
|
||||
/// Section for newer gnu pubtypes.
|
||||
MCSection *DwarfGnuPubTypesSection;
|
||||
|
||||
MCSection *COFFDebugSymbolsSection;
|
||||
|
||||
// Extra TLS Variable Data section. If the target needs to put additional
|
||||
// information for a TLS variable, it'll go here.
|
||||
/// Extra TLS Variable Data section.
|
||||
///
|
||||
/// If the target needs to put additional information for a TLS variable,
|
||||
/// it'll go here.
|
||||
MCSection *TLSExtraDataSection;
|
||||
|
||||
/// Section directive for Thread Local data. ELF, MachO and COFF.
|
||||
MCSection *TLSDataSection; // Defaults to ".tdata".
|
||||
|
||||
/// Section directive for Thread Local uninitialized data. Null if this target
|
||||
/// doesn't support a BSS section. ELF and MachO only.
|
||||
/// Section directive for Thread Local uninitialized data.
|
||||
///
|
||||
/// Null if this target doesn't support a BSS section. ELF and MachO only.
|
||||
MCSection *TLSBSSSection; // Defaults to ".tbss".
|
||||
|
||||
/// StackMap section.
|
||||
MCSection *StackMapSection;
|
||||
|
||||
/// EH frame section. It is initialized on demand so it can be overwritten
|
||||
/// (with uniquing).
|
||||
/// EH frame section.
|
||||
///
|
||||
/// It is initialized on demand so it can be overwritten (with uniquing).
|
||||
MCSection *EHFrameSection;
|
||||
|
||||
/// ELF specific sections.
|
||||
///
|
||||
// ELF specific sections.
|
||||
MCSection *DataRelSection;
|
||||
const MCSection *DataRelLocalSection;
|
||||
MCSection *DataRelROSection;
|
||||
@ -155,17 +153,16 @@ class MCObjectFileInfo {
|
||||
MCSection *MergeableConst8Section;
|
||||
MCSection *MergeableConst16Section;
|
||||
|
||||
/// MachO specific sections.
|
||||
///
|
||||
// MachO specific sections.
|
||||
|
||||
/// Section for thread local structure information. Contains the source code
|
||||
/// name of the variable, visibility and a pointer to the initial value
|
||||
/// (.tdata or .tbss).
|
||||
/// Section for thread local structure information.
|
||||
///
|
||||
/// Contains the source code name of the variable, visibility and a pointer to
|
||||
/// the initial value (.tdata or .tbss).
|
||||
MCSection *TLSTLVSection; // Defaults to ".tlv".
|
||||
|
||||
/// TLSThreadInitSection - Section for thread local data initialization
|
||||
/// functions.
|
||||
const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func".
|
||||
/// Section for thread local data initialization functions.
|
||||
const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func".
|
||||
|
||||
MCSection *CStringSection;
|
||||
MCSection *UStringSection;
|
||||
@ -182,10 +179,10 @@ class MCObjectFileInfo {
|
||||
MCSection *NonLazySymbolPointerSection;
|
||||
|
||||
/// COFF specific sections.
|
||||
///
|
||||
MCSection *DrectveSection;
|
||||
MCSection *PDataSection;
|
||||
MCSection *XDataSection;
|
||||
MCSection *SXDataSection;
|
||||
|
||||
public:
|
||||
void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM,
|
||||
@ -266,8 +263,7 @@ class MCObjectFileInfo {
|
||||
|
||||
MCSection *getStackMapSection() const { return StackMapSection; }
|
||||
|
||||
/// ELF specific sections.
|
||||
///
|
||||
// ELF specific sections.
|
||||
MCSection *getDataRelSection() const { return DataRelSection; }
|
||||
const MCSection *getDataRelLocalSection() const {
|
||||
return DataRelLocalSection;
|
||||
@ -284,8 +280,7 @@ class MCObjectFileInfo {
|
||||
return MergeableConst16Section;
|
||||
}
|
||||
|
||||
/// MachO specific sections.
|
||||
///
|
||||
// MachO specific sections.
|
||||
const MCSection *getTLSTLVSection() const { return TLSTLVSection; }
|
||||
const MCSection *getTLSThreadInitSection() const {
|
||||
return TLSThreadInitSection;
|
||||
@ -316,11 +311,11 @@ class MCObjectFileInfo {
|
||||
return NonLazySymbolPointerSection;
|
||||
}
|
||||
|
||||
/// COFF specific sections.
|
||||
///
|
||||
// COFF specific sections.
|
||||
MCSection *getDrectveSection() const { return DrectveSection; }
|
||||
MCSection *getPDataSection() const { return PDataSection; }
|
||||
MCSection *getXDataSection() const { return XDataSection; }
|
||||
MCSection *getSXDataSection() const { return SXDataSection; }
|
||||
|
||||
MCSection *getEHFrameSection() {
|
||||
if (!EHFrameSection)
|
||||
@ -329,13 +324,9 @@ class MCObjectFileInfo {
|
||||
}
|
||||
|
||||
enum Environment { IsMachO, IsELF, IsCOFF };
|
||||
Environment getObjectFileType() const {
|
||||
return Env;
|
||||
}
|
||||
Environment getObjectFileType() const { return Env; }
|
||||
|
||||
Reloc::Model getRelocM() const {
|
||||
return RelocM;
|
||||
}
|
||||
Reloc::Model getRelocM() const { return RelocM; }
|
||||
|
||||
private:
|
||||
Environment Env;
|
||||
@ -344,12 +335,11 @@ class MCObjectFileInfo {
|
||||
MCContext *Ctx;
|
||||
Triple TT;
|
||||
|
||||
void InitMachOMCObjectFileInfo(Triple T);
|
||||
void InitELFMCObjectFileInfo(Triple T);
|
||||
void InitCOFFMCObjectFileInfo(Triple T);
|
||||
void initMachOMCObjectFileInfo(Triple T);
|
||||
void initELFMCObjectFileInfo(Triple T);
|
||||
void initCOFFMCObjectFileInfo(Triple T);
|
||||
|
||||
/// InitEHFrameSection - Initialize EHFrameSection on demand.
|
||||
///
|
||||
/// Initialize EHFrameSection on demand.
|
||||
void InitEHFrameSection();
|
||||
|
||||
public:
|
||||
|
@ -35,11 +35,10 @@ class raw_pwrite_stream;
|
||||
/// implementation.
|
||||
class MCObjectStreamer : public MCStreamer {
|
||||
MCAssembler *Assembler;
|
||||
MCSection *CurSectionData;
|
||||
MCSection::iterator CurInsertionPoint;
|
||||
bool EmitEHFrame;
|
||||
bool EmitDebugFrame;
|
||||
SmallVector<MCSymbolData *, 2> PendingLabels;
|
||||
SmallVector<MCSymbol *, 2> PendingLabels;
|
||||
|
||||
virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0;
|
||||
void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
|
||||
@ -57,21 +56,17 @@ class MCObjectStreamer : public MCStreamer {
|
||||
/// Object streamers require the integrated assembler.
|
||||
bool isIntegratedAssemblerRequired() const override { return true; }
|
||||
|
||||
MCSymbolData &getOrCreateSymbolData(const MCSymbol *Symbol) {
|
||||
return getAssembler().getOrCreateSymbolData(*Symbol);
|
||||
}
|
||||
void EmitFrames(MCAsmBackend *MAB);
|
||||
void EmitCFISections(bool EH, bool Debug) override;
|
||||
|
||||
protected:
|
||||
MCSection *getCurrentSectionData() const { return CurSectionData; }
|
||||
|
||||
MCFragment *getCurrentFragment() const;
|
||||
|
||||
void insert(MCFragment *F) {
|
||||
flushPendingLabels(F);
|
||||
CurSectionData->getFragmentList().insert(CurInsertionPoint, F);
|
||||
F->setParent(CurSectionData);
|
||||
MCSection *CurSection = getCurrentSectionOnly();
|
||||
CurSection->getFragmentList().insert(CurInsertionPoint, F);
|
||||
F->setParent(CurSection);
|
||||
}
|
||||
|
||||
/// Get a data fragment to write into, creating a new one if the current
|
||||
|
@ -22,18 +22,17 @@ class MCAsmLayout;
|
||||
class MCAssembler;
|
||||
class MCFixup;
|
||||
class MCFragment;
|
||||
class MCSymbolData;
|
||||
class MCSymbolRefExpr;
|
||||
class MCValue;
|
||||
|
||||
/// MCObjectWriter - Defines the object file and target independent interfaces
|
||||
/// used by the assembler backend to write native file format object files.
|
||||
/// Defines the object file and target independent interfaces used by the
|
||||
/// 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 to modify the assembler data structures at appropriate
|
||||
/// points. Once assembly is complete, the object writer is given the
|
||||
/// 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
|
||||
/// binary data to the output stream.
|
||||
@ -54,7 +53,7 @@ class MCObjectWriter {
|
||||
virtual ~MCObjectWriter();
|
||||
|
||||
/// lifetime management
|
||||
virtual void reset() { }
|
||||
virtual void reset() {}
|
||||
|
||||
bool isLittleEndian() const { return IsLittleEndian; }
|
||||
|
||||
@ -63,109 +62,106 @@ class MCObjectWriter {
|
||||
/// \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).
|
||||
///
|
||||
/// This routine is called by the assembler after layout and relaxation is
|
||||
/// complete.
|
||||
virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
|
||||
virtual void executePostLayoutBinding(MCAssembler &Asm,
|
||||
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
|
||||
/// post layout binding. The implementation is responsible for storing
|
||||
/// information about the relocation so that it can be emitted during
|
||||
/// WriteObject().
|
||||
virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
/// writeObject().
|
||||
virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
bool &IsPCRel, uint64_t &FixedValue) = 0;
|
||||
|
||||
/// \brief Check whether the difference (A - B) between two symbol
|
||||
/// references is fully resolved.
|
||||
/// Check whether the difference (A - B) between two symbol references is
|
||||
/// fully resolved.
|
||||
///
|
||||
/// Clients are not required to answer precisely and may conservatively return
|
||||
/// false, even when a difference is fully resolved.
|
||||
bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
|
||||
bool isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
|
||||
const MCSymbolRefExpr *A,
|
||||
const MCSymbolRefExpr *B,
|
||||
bool InSet) const;
|
||||
|
||||
virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
const MCSymbol &SymA,
|
||||
const MCFragment &FB,
|
||||
bool InSet,
|
||||
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
|
||||
/// past it.
|
||||
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
|
||||
/// complete, fixups have been evaluated and applied, and relocations
|
||||
/// generated.
|
||||
virtual void WriteObject(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) = 0;
|
||||
virtual void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0;
|
||||
|
||||
/// @}
|
||||
/// \name Binary Output
|
||||
/// @{
|
||||
|
||||
void Write8(uint8_t Value) {
|
||||
OS << char(Value);
|
||||
}
|
||||
void write8(uint8_t Value) { OS << char(Value); }
|
||||
|
||||
void WriteLE16(uint16_t Value) {
|
||||
void writeLE16(uint16_t 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);
|
||||
}
|
||||
|
||||
void WriteLE64(uint64_t Value) {
|
||||
void writeLE64(uint64_t 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);
|
||||
}
|
||||
|
||||
void WriteBE32(uint32_t Value) {
|
||||
void writeBE32(uint32_t 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);
|
||||
}
|
||||
|
||||
void Write16(uint16_t Value) {
|
||||
void write16(uint16_t Value) {
|
||||
if (IsLittleEndian)
|
||||
WriteLE16(Value);
|
||||
writeLE16(Value);
|
||||
else
|
||||
WriteBE16(Value);
|
||||
writeBE16(Value);
|
||||
}
|
||||
|
||||
void Write32(uint32_t Value) {
|
||||
void write32(uint32_t Value) {
|
||||
if (IsLittleEndian)
|
||||
WriteLE32(Value);
|
||||
writeLE32(Value);
|
||||
else
|
||||
WriteBE32(Value);
|
||||
writeBE32(Value);
|
||||
}
|
||||
|
||||
void Write64(uint64_t Value) {
|
||||
void write64(uint64_t Value) {
|
||||
if (IsLittleEndian)
|
||||
WriteLE64(Value);
|
||||
writeLE64(Value);
|
||||
else
|
||||
WriteBE64(Value);
|
||||
writeBE64(Value);
|
||||
}
|
||||
|
||||
void WriteZeros(unsigned N) {
|
||||
const char Zeros[16] = { 0 };
|
||||
const char Zeros[16] = {0};
|
||||
|
||||
for (unsigned i = 0, e = N / 16; i != e; ++i)
|
||||
OS << StringRef(Zeros, 16);
|
||||
@ -173,22 +169,23 @@ class MCObjectWriter {
|
||||
OS << StringRef(Zeros, N % 16);
|
||||
}
|
||||
|
||||
void WriteBytes(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) {
|
||||
WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
|
||||
void writeBytes(const SmallVectorImpl<char> &ByteVec,
|
||||
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
|
||||
// converted to SmallVector<char, N>
|
||||
assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
|
||||
"data size greater than fill size, unexpected large write will occur");
|
||||
assert(
|
||||
(ZeroFillSize == 0 || Str.size() <= ZeroFillSize) &&
|
||||
"data size greater than fill size, unexpected large write will occur");
|
||||
OS << Str;
|
||||
if (ZeroFillSize)
|
||||
WriteZeros(ZeroFillSize - Str.size());
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -73,11 +73,13 @@ class MCSection {
|
||||
|
||||
/// \brief We've seen a bundle_lock directive but not its first instruction
|
||||
/// yet.
|
||||
bool BundleGroupBeforeFirstInst = false;
|
||||
unsigned BundleGroupBeforeFirstInst : 1;
|
||||
|
||||
/// Whether this section has had instructions emitted into it.
|
||||
unsigned HasInstructions : 1;
|
||||
|
||||
unsigned IsRegistered : 1;
|
||||
|
||||
FragmentListType Fragments;
|
||||
|
||||
/// Mapping from subsection number to insertion point for subsection numbers
|
||||
@ -130,6 +132,9 @@ class MCSection {
|
||||
bool hasInstructions() const { return HasInstructions; }
|
||||
void setHasInstructions(bool Value) { HasInstructions = Value; }
|
||||
|
||||
bool isRegistered() const { return IsRegistered; }
|
||||
void setIsRegistered(bool Value) { IsRegistered = Value; }
|
||||
|
||||
MCSection::FragmentListType &getFragmentList() { return Fragments; }
|
||||
const MCSection::FragmentListType &getFragmentList() const {
|
||||
return const_cast<MCSection *>(this)->getFragmentList();
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/MC/MCSection.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ELF.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.
|
||||
unsigned EntrySize;
|
||||
|
||||
const MCSymbol *Group;
|
||||
const MCSymbolELF *Group;
|
||||
|
||||
/// Depending on the type of the section this is sh_link or sh_info.
|
||||
const MCSectionELF *Associated;
|
||||
@ -54,11 +54,14 @@ class MCSectionELF : public MCSection {
|
||||
private:
|
||||
friend class MCContext;
|
||||
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)
|
||||
: MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type),
|
||||
Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group),
|
||||
Associated(Associated) {}
|
||||
Associated(Associated) {
|
||||
if (Group)
|
||||
Group->setIsSignature();
|
||||
}
|
||||
~MCSectionELF() override;
|
||||
|
||||
void setSectionName(StringRef Name) { SectionName = Name; }
|
||||
@ -73,7 +76,7 @@ class MCSectionELF : public MCSection {
|
||||
unsigned getType() const { return Type; }
|
||||
unsigned getFlags() const { return Flags; }
|
||||
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,
|
||||
const MCExpr *Subsection) const override;
|
||||
|
@ -34,6 +34,7 @@ class MCInstPrinter;
|
||||
class MCSection;
|
||||
class MCStreamer;
|
||||
class MCSymbol;
|
||||
class MCSymbolELF;
|
||||
class MCSymbolRefExpr;
|
||||
class MCSubtargetInfo;
|
||||
class StringRef;
|
||||
@ -272,6 +273,7 @@ class MCStreamer {
|
||||
return SectionStack.back().first;
|
||||
return MCSectionSubPair();
|
||||
}
|
||||
MCSection *getCurrentSectionOnly() const { return getCurrentSection().first; }
|
||||
|
||||
/// \brief Return the previous section that the streamer is emitting code to.
|
||||
MCSectionSubPair getPreviousSection() const {
|
||||
@ -305,11 +307,15 @@ class MCStreamer {
|
||||
bool PopSection() {
|
||||
if (SectionStack.size() <= 1)
|
||||
return false;
|
||||
MCSectionSubPair oldSection = SectionStack.pop_back_val().first;
|
||||
MCSectionSubPair curSection = SectionStack.back().first;
|
||||
auto I = SectionStack.end();
|
||||
--I;
|
||||
MCSectionSubPair OldSection = I->first;
|
||||
--I;
|
||||
MCSectionSubPair NewSection = I->first;
|
||||
|
||||
if (oldSection != curSection)
|
||||
ChangeSection(curSection.first, curSection.second);
|
||||
if (OldSection != NewSection)
|
||||
ChangeSection(NewSection.first, NewSection.second);
|
||||
SectionStack.pop_back();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -433,6 +439,8 @@ class MCStreamer {
|
||||
/// \brief Marks the end of the symbol definition.
|
||||
virtual void EndCOFFSymbolDef();
|
||||
|
||||
virtual void EmitCOFFSafeSEH(MCSymbol const *Symbol);
|
||||
|
||||
/// \brief Emits a COFF section index.
|
||||
///
|
||||
/// \param Symbol - Symbol the section number relocation should point to.
|
||||
@ -447,7 +455,7 @@ class MCStreamer {
|
||||
///
|
||||
/// This corresponds to an assembler statement such as:
|
||||
/// .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.
|
||||
/// \param Args - Arguments of the LOH.
|
||||
|
@ -73,7 +73,9 @@ class MCSubtargetInfo {
|
||||
|
||||
/// 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
|
||||
/// feature string). Recompute feature bits and scheduling model.
|
||||
@ -94,6 +96,10 @@ class MCSubtargetInfo {
|
||||
/// feature bits. This version will also change all implied bits.
|
||||
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.
|
||||
///
|
||||
MCSchedModel getSchedModelForCPU(StringRef CPU) const;
|
||||
|
@ -14,12 +14,14 @@
|
||||
#ifndef 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/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmInfo;
|
||||
class MCExpr;
|
||||
class MCSymbol;
|
||||
class MCFragment;
|
||||
@ -27,109 +29,6 @@ class MCSection;
|
||||
class MCContext;
|
||||
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,
|
||||
/// and MCSymbols are created and uniqued by the MCContext class. MCSymbols
|
||||
/// 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
|
||||
/// it is a reference to an external entity, it has a null section.
|
||||
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.
|
||||
//
|
||||
// FIXME: Use a PointerInt wrapper for this?
|
||||
@ -147,10 +56,18 @@ class MCSymbol {
|
||||
/// held by the StringMap that lives in MCContext.
|
||||
const StringMapEntry<bool> *Name;
|
||||
|
||||
/// The section 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.
|
||||
mutable MCSection *Section;
|
||||
/// If a symbol has a Fragment, the section is implied, so we only need
|
||||
/// one pointer.
|
||||
/// FIXME: We might be able to simplify this by having the asm streamer create
|
||||
/// 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.
|
||||
const MCExpr *Value;
|
||||
@ -166,46 +83,68 @@ class MCSymbol {
|
||||
/// IsUsed - True if this symbol has been used.
|
||||
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.
|
||||
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 MCContext;
|
||||
MCSymbol(const StringMapEntry<bool> *Name, bool isTemporary)
|
||||
: Name(Name), Section(nullptr), Value(nullptr), IsTemporary(isTemporary),
|
||||
IsRedefinable(false), IsUsed(false), HasData(false), Index(0) {}
|
||||
MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary)
|
||||
: Name(Name), Value(nullptr), IsTemporary(isTemporary),
|
||||
IsRedefinable(false), IsUsed(false), IsRegistered(false),
|
||||
IsExternal(false), IsPrivateExtern(false),
|
||||
Kind(Kind) {
|
||||
Offset = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
MCSymbol(const MCSymbol &) = delete;
|
||||
void operator=(const MCSymbol &) = delete;
|
||||
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)
|
||||
return Section;
|
||||
return Section = Value->FindAssociatedSection();
|
||||
return Section = Value->findAssociatedSection();
|
||||
}
|
||||
|
||||
public:
|
||||
/// getName - Get the symbol name.
|
||||
StringRef getName() const { return Name ? Name->first() : ""; }
|
||||
|
||||
bool hasData() const { return HasData; }
|
||||
|
||||
/// 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; }
|
||||
bool isRegistered() const { return IsRegistered; }
|
||||
void setIsRegistered(bool Value) const { IsRegistered = Value; }
|
||||
|
||||
/// \name Accessors
|
||||
/// @{
|
||||
@ -225,7 +164,7 @@ class MCSymbol {
|
||||
void redefineIfPossible() {
|
||||
if (IsRedefinable) {
|
||||
Value = nullptr;
|
||||
Section = nullptr;
|
||||
SectionOrFragment = nullptr;
|
||||
IsRedefinable = false;
|
||||
}
|
||||
}
|
||||
@ -258,11 +197,20 @@ class MCSymbol {
|
||||
/// Mark the symbol as defined in the section \p S.
|
||||
void setSection(MCSection &S) {
|
||||
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.
|
||||
void setUndefined() { Section = nullptr; }
|
||||
/// Mark the symbol as undefined.
|
||||
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
|
||||
@ -283,27 +231,98 @@ class MCSymbol {
|
||||
/// @}
|
||||
|
||||
/// Get the (implementation defined) index.
|
||||
uint64_t getIndex() const {
|
||||
assert(HasData && "Uninitialized symbol data");
|
||||
uint32_t getIndex() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
/// Set the (implementation defined) index.
|
||||
void setIndex(uint64_t Value) const {
|
||||
assert(HasData && "Uninitialized symbol data");
|
||||
assert(!(Value >> 60) && "Not enough bits for value");
|
||||
void setIndex(uint32_t Value) const {
|
||||
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.
|
||||
void print(raw_ostream &OS) const;
|
||||
void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
|
||||
|
||||
/// dump - Print the value to stderr.
|
||||
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) {
|
||||
Sym.print(OS);
|
||||
Sym.print(OS, nullptr);
|
||||
return OS;
|
||||
}
|
||||
} // 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 EmitCOFFSymbolType(int Type) override;
|
||||
void EndCOFFSymbolDef() override;
|
||||
void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
|
||||
void EmitCOFFSectionIndex(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,
|
||||
unsigned ByteAlignment) override;
|
||||
void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||
|
@ -103,6 +103,10 @@ class SubtargetFeatures {
|
||||
FeatureBitset ToggleFeature(FeatureBitset Bits, StringRef String,
|
||||
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.
|
||||
FeatureBitset getFeatureBits(StringRef CPU,
|
||||
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;
|
||||
std::error_code getSymbolAddress(DataRefImpl Symb,
|
||||
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;
|
||||
std::error_code getSymbolType(DataRefImpl Symb,
|
||||
SymbolRef::Type &Res) const override;
|
||||
@ -647,10 +647,6 @@ class COFFObjectFile : public ObjectFile {
|
||||
std::error_code
|
||||
getRelocationTypeName(DataRefImpl Rel,
|
||||
SmallVectorImpl<char> &Result) const override;
|
||||
std::error_code
|
||||
getRelocationValueString(DataRefImpl Rel,
|
||||
SmallVectorImpl<char> &Result) const override;
|
||||
|
||||
public:
|
||||
COFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
|
||||
basic_symbol_iterator symbol_begin_impl() const override;
|
||||
@ -699,7 +695,7 @@ class COFFObjectFile : public ObjectFile {
|
||||
return object_error::parse_failed;
|
||||
|
||||
Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const {
|
||||
if (SymbolTable16) {
|
||||
@ -722,7 +718,7 @@ class COFFObjectFile : public ObjectFile {
|
||||
if (std::error_code EC = s.getError())
|
||||
return EC;
|
||||
Res = reinterpret_cast<const T *>(s->getRawPtr());
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;
|
||||
|
||||
|
@ -318,7 +318,7 @@ class ELFFile {
|
||||
std::pair<const Elf_Shdr *, const Elf_Sym *>
|
||||
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 {
|
||||
return Header->e_machine == ELF::EM_MIPS &&
|
||||
@ -423,12 +423,10 @@ class ELFFile {
|
||||
StringRef getLoadName() const;
|
||||
};
|
||||
|
||||
// Use an alignment of 2 for the typedefs since that is the worst case for
|
||||
// ELF files in archives.
|
||||
typedef ELFFile<ELFType<support::little, 2, false> > ELF32LEFile;
|
||||
typedef ELFFile<ELFType<support::little, 2, true> > ELF64LEFile;
|
||||
typedef ELFFile<ELFType<support::big, 2, false> > ELF32BEFile;
|
||||
typedef ELFFile<ELFType<support::big, 2, true> > ELF64BEFile;
|
||||
typedef ELFFile<ELFType<support::little, false>> ELF32LEFile;
|
||||
typedef ELFFile<ELFType<support::little, true>> ELF64LEFile;
|
||||
typedef ELFFile<ELFType<support::big, false>> ELF32BEFile;
|
||||
typedef ELFFile<ELFType<support::big, true>> ELF64BEFile;
|
||||
|
||||
// Iterate through the version definitions, and place each Elf_Verdef
|
||||
// in the VersionMap according to its index.
|
||||
@ -622,7 +620,7 @@ typename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const {
|
||||
}
|
||||
|
||||
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),
|
||||
dot_strtab_sec(nullptr), dot_symtab_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) {
|
||||
const uint64_t FileSize = Buf.size();
|
||||
|
||||
if (sizeof(Elf_Ehdr) > FileSize)
|
||||
// FIXME: Proper error handling.
|
||||
report_fatal_error("File too short!");
|
||||
if (sizeof(Elf_Ehdr) > FileSize) {
|
||||
// File too short!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)
|
||||
// FIXME: Proper error handling.
|
||||
report_fatal_error("Section header table goes past end of file!");
|
||||
if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) {
|
||||
// Section header table goes past end of file!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
|
||||
// The getNumSections() call below depends on SectionHeaderTable being set.
|
||||
SectionHeaderTable =
|
||||
reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
|
||||
const uint64_t SectionTableSize = getNumSections() * Header->e_shentsize;
|
||||
|
||||
if (SectionTableOffset + SectionTableSize > FileSize)
|
||||
// FIXME: Proper error handling.
|
||||
report_fatal_error("Section table goes past end of file!");
|
||||
if (SectionTableOffset + SectionTableSize > FileSize) {
|
||||
// Section table goes past end of file!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
|
||||
// Scan sections for special sections.
|
||||
|
||||
for (const Elf_Shdr &Sec : sections()) {
|
||||
switch (Sec.sh_type) {
|
||||
case ELF::SHT_SYMTAB_SHNDX:
|
||||
if (SymbolTableSectionHeaderIndex)
|
||||
// FIXME: Proper error handling.
|
||||
report_fatal_error("More than one .symtab_shndx!");
|
||||
if (SymbolTableSectionHeaderIndex) {
|
||||
// More than one .symtab_shndx!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
SymbolTableSectionHeaderIndex = &Sec;
|
||||
break;
|
||||
case ELF::SHT_SYMTAB:
|
||||
if (dot_symtab_sec)
|
||||
// FIXME: Proper error handling.
|
||||
report_fatal_error("More than one .symtab!");
|
||||
if (dot_symtab_sec) {
|
||||
// More than one .symtab!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
dot_symtab_sec = &Sec;
|
||||
dot_strtab_sec = getSection(Sec.sh_link);
|
||||
break;
|
||||
case ELF::SHT_DYNSYM: {
|
||||
if (DynSymRegion.Addr)
|
||||
// FIXME: Proper error handling.
|
||||
report_fatal_error("More than one .dynsym!");
|
||||
if (DynSymRegion.Addr) {
|
||||
// More than one .dynsym!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
DynSymRegion.Addr = base() + Sec.sh_offset;
|
||||
DynSymRegion.Size = Sec.sh_size;
|
||||
DynSymRegion.EntSize = Sec.sh_entsize;
|
||||
@ -685,29 +695,37 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &ec)
|
||||
break;
|
||||
}
|
||||
case ELF::SHT_DYNAMIC:
|
||||
if (DynamicRegion.Addr)
|
||||
// FIXME: Proper error handling.
|
||||
report_fatal_error("More than one .dynamic!");
|
||||
if (DynamicRegion.Addr) {
|
||||
// More than one .dynamic!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
DynamicRegion.Addr = base() + Sec.sh_offset;
|
||||
DynamicRegion.Size = Sec.sh_size;
|
||||
DynamicRegion.EntSize = Sec.sh_entsize;
|
||||
break;
|
||||
case ELF::SHT_GNU_versym:
|
||||
if (dot_gnu_version_sec != nullptr)
|
||||
// FIXME: Proper error handling.
|
||||
report_fatal_error("More than one .gnu.version section!");
|
||||
if (dot_gnu_version_sec != nullptr) {
|
||||
// More than one .gnu.version section!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
dot_gnu_version_sec = &Sec;
|
||||
break;
|
||||
case ELF::SHT_GNU_verdef:
|
||||
if (dot_gnu_version_d_sec != nullptr)
|
||||
// FIXME: Proper error handling.
|
||||
report_fatal_error("More than one .gnu.version_d section!");
|
||||
if (dot_gnu_version_d_sec != nullptr) {
|
||||
// More than one .gnu.version_d section!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
dot_gnu_version_d_sec = &Sec;
|
||||
break;
|
||||
case ELF::SHT_GNU_verneed:
|
||||
if (dot_gnu_version_r_sec != nullptr)
|
||||
// FIXME: Proper error handling.
|
||||
report_fatal_error("More than one .gnu.version_r section!");
|
||||
if (dot_gnu_version_r_sec != nullptr) {
|
||||
// More than one .gnu.version_r section!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
dot_gnu_version_r_sec = &Sec;
|
||||
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
|
||||
@ -898,11 +916,8 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(Elf_Sym_Iter Sym) const {
|
||||
template <class ELFT>
|
||||
ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Shdr *Section,
|
||||
const Elf_Sym *Symb) const {
|
||||
if (Symb->st_name == 0) {
|
||||
const Elf_Shdr *ContainingSec = getSection(Symb);
|
||||
if (ContainingSec)
|
||||
return getSectionName(ContainingSec);
|
||||
}
|
||||
if (Symb->st_name == 0)
|
||||
return StringRef("");
|
||||
|
||||
const Elf_Shdr *StrTab = getSection(Section->sh_link);
|
||||
if (Symb->st_name >= StrTab->sh_size)
|
||||
|
@ -79,9 +79,8 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
|
||||
StringRef &Res) const override;
|
||||
std::error_code getSymbolAddress(DataRefImpl Symb,
|
||||
uint64_t &Res) const override;
|
||||
std::error_code getSymbolAlignment(DataRefImpl Symb,
|
||||
uint32_t &Res) const override;
|
||||
std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override;
|
||||
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
|
||||
uint64_t getSymbolSize(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 getSymbolType(DataRefImpl Symb,
|
||||
@ -119,9 +118,6 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
|
||||
std::error_code
|
||||
getRelocationTypeName(DataRefImpl Rel,
|
||||
SmallVectorImpl<char> &Result) const override;
|
||||
std::error_code
|
||||
getRelocationValueString(DataRefImpl Rel,
|
||||
SmallVectorImpl<char> &Result) const override;
|
||||
|
||||
uint64_t getROffset(DataRefImpl Rel) 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 {
|
||||
Result = EF.getHeader()->e_flags;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
const ELFFile<ELFT> *getELFFile() const { return &EF; }
|
||||
@ -244,12 +240,10 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
|
||||
bool isRelocatableObject() const override;
|
||||
};
|
||||
|
||||
// Use an alignment of 2 for the typedefs since that is the worst case for
|
||||
// ELF files in archives.
|
||||
typedef ELFObjectFile<ELFType<support::little, 2, false> > ELF32LEObjectFile;
|
||||
typedef ELFObjectFile<ELFType<support::little, 2, true> > ELF64LEObjectFile;
|
||||
typedef ELFObjectFile<ELFType<support::big, 2, false> > ELF32BEObjectFile;
|
||||
typedef ELFObjectFile<ELFType<support::big, 2, true> > ELF64BEObjectFile;
|
||||
typedef ELFObjectFile<ELFType<support::little, false>> ELF32LEObjectFile;
|
||||
typedef ELFObjectFile<ELFType<support::little, true>> ELF64LEObjectFile;
|
||||
typedef ELFObjectFile<ELFType<support::big, false>> ELF32BEObjectFile;
|
||||
typedef ELFObjectFile<ELFType<support::big, true>> ELF64BEObjectFile;
|
||||
|
||||
template <class ELFT>
|
||||
void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Symb) const {
|
||||
@ -263,7 +257,7 @@ std::error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb,
|
||||
if (!Name)
|
||||
return Name.getError();
|
||||
Result = *Name;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -277,7 +271,7 @@ std::error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef,
|
||||
if (!Ver)
|
||||
return Ver.getError();
|
||||
Version = *Ver;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -300,10 +294,10 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
|
||||
case ELF::SHN_COMMON:
|
||||
case ELF::SHN_UNDEF:
|
||||
Result = UnknownAddressOrSize;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
case ELF::SHN_ABS:
|
||||
Result = ESym->st_value;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -322,32 +316,27 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
|
||||
Result += Section->sh_addr;
|
||||
}
|
||||
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
std::error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb,
|
||||
uint32_t &Res) const {
|
||||
uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const {
|
||||
Elf_Sym_Iter Sym = toELFSymIter(Symb);
|
||||
if (Sym->st_shndx == ELF::SHN_COMMON)
|
||||
Res = Sym->st_value;
|
||||
else
|
||||
Res = 0;
|
||||
return object_error::success;
|
||||
return Sym->st_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
std::error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb,
|
||||
uint64_t &Result) const {
|
||||
Result = toELFSymIter(Symb)->st_size;
|
||||
return object_error::success;
|
||||
uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb) const {
|
||||
return toELFSymIter(Symb)->st_size;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
std::error_code ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb,
|
||||
uint8_t &Result) const {
|
||||
Result = toELFSymIter(Symb)->st_other;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -378,7 +367,7 @@ ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb,
|
||||
Result = SymbolRef::ST_Other;
|
||||
break;
|
||||
}
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -435,7 +424,7 @@ std::error_code
|
||||
ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
|
||||
section_iterator &Res) const {
|
||||
Res = getSymbolSection(getSymbol(Symb));
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -450,7 +439,7 @@ std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec,
|
||||
if (!Name)
|
||||
return Name.getError();
|
||||
Result = *Name;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -469,7 +458,7 @@ ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec,
|
||||
StringRef &Result) const {
|
||||
Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
|
||||
Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size);
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -624,7 +613,7 @@ ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel,
|
||||
Result = ROffset;
|
||||
}
|
||||
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -634,7 +623,7 @@ ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel,
|
||||
assert(EF.getHeader()->e_type == ELF::ET_REL &&
|
||||
"Only relocatable object files have relocation offsets");
|
||||
Result = getROffset(Rel);
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -666,7 +655,7 @@ std::error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel,
|
||||
break;
|
||||
}
|
||||
}
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -693,7 +682,7 @@ std::error_code ELFObjectFile<ELFT>::getRelocationTypeName(
|
||||
}
|
||||
|
||||
EF.getRelocationTypeName(type, Result);
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -706,96 +695,15 @@ ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel,
|
||||
report_fatal_error("Invalid section type in Rel!");
|
||||
case ELF::SHT_REL: {
|
||||
Result = 0;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
case ELF::SHT_RELA: {
|
||||
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>
|
||||
const typename ELFFile<ELFT>::Elf_Sym *
|
||||
ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const {
|
||||
|
@ -10,7 +10,6 @@
|
||||
#ifndef LLVM_OBJECT_ELFTYPES_H
|
||||
#define LLVM_OBJECT_ELFTYPES_H
|
||||
|
||||
#include "llvm/Support/AlignOf.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
@ -20,95 +19,74 @@ namespace object {
|
||||
|
||||
using support::endianness;
|
||||
|
||||
template <endianness target_endianness, std::size_t max_alignment,
|
||||
bool is64Bits>
|
||||
struct ELFType {
|
||||
template <endianness target_endianness, bool is64Bits> struct ELFType {
|
||||
static const endianness TargetEndianness = target_endianness;
|
||||
static const std::size_t MaxAlignment = max_alignment;
|
||||
static const bool Is64Bits = is64Bits;
|
||||
};
|
||||
|
||||
template <typename T, int max_align> struct MaximumAlignment {
|
||||
enum { value = AlignOf<T>::Alignment > max_align ? max_align
|
||||
: AlignOf<T>::Alignment
|
||||
};
|
||||
};
|
||||
// Use an alignment of 2 for the typedefs since that is the worst case for
|
||||
// ELF files in archives.
|
||||
|
||||
// Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
|
||||
template <endianness target_endianness, std::size_t max_alignment>
|
||||
struct ELFDataTypeTypedefHelperCommon {
|
||||
template <endianness target_endianness> struct ELFDataTypeTypedefHelperCommon {
|
||||
typedef support::detail::packed_endian_specific_integral<
|
||||
uint16_t, target_endianness,
|
||||
MaximumAlignment<uint16_t, max_alignment>::value> Elf_Half;
|
||||
uint16_t, target_endianness, 2> Elf_Half;
|
||||
typedef support::detail::packed_endian_specific_integral<
|
||||
uint32_t, target_endianness,
|
||||
MaximumAlignment<uint32_t, max_alignment>::value> Elf_Word;
|
||||
uint32_t, target_endianness, 2> Elf_Word;
|
||||
typedef support::detail::packed_endian_specific_integral<
|
||||
int32_t, target_endianness,
|
||||
MaximumAlignment<int32_t, max_alignment>::value> Elf_Sword;
|
||||
int32_t, target_endianness, 2> Elf_Sword;
|
||||
typedef support::detail::packed_endian_specific_integral<
|
||||
uint64_t, target_endianness,
|
||||
MaximumAlignment<uint64_t, max_alignment>::value> Elf_Xword;
|
||||
uint64_t, target_endianness, 2> Elf_Xword;
|
||||
typedef support::detail::packed_endian_specific_integral<
|
||||
int64_t, target_endianness,
|
||||
MaximumAlignment<int64_t, max_alignment>::value> Elf_Sxword;
|
||||
int64_t, target_endianness, 2> Elf_Sxword;
|
||||
};
|
||||
|
||||
template <class ELFT> struct ELFDataTypeTypedefHelper;
|
||||
|
||||
/// ELF 32bit types.
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, false> >
|
||||
: ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> {
|
||||
template <endianness TargetEndianness>
|
||||
struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, false>>
|
||||
: ELFDataTypeTypedefHelperCommon<TargetEndianness> {
|
||||
typedef uint32_t value_type;
|
||||
typedef support::detail::packed_endian_specific_integral<
|
||||
value_type, TargetEndianness,
|
||||
MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr;
|
||||
value_type, TargetEndianness, 2> Elf_Addr;
|
||||
typedef support::detail::packed_endian_specific_integral<
|
||||
value_type, TargetEndianness,
|
||||
MaximumAlignment<value_type, MaxAlign>::value> Elf_Off;
|
||||
value_type, TargetEndianness, 2> Elf_Off;
|
||||
};
|
||||
|
||||
/// ELF 64bit types.
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, true> >
|
||||
: ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> {
|
||||
template <endianness TargetEndianness>
|
||||
struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>>
|
||||
: ELFDataTypeTypedefHelperCommon<TargetEndianness> {
|
||||
typedef uint64_t value_type;
|
||||
typedef support::detail::packed_endian_specific_integral<
|
||||
value_type, TargetEndianness,
|
||||
MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr;
|
||||
value_type, TargetEndianness, 2> Elf_Addr;
|
||||
typedef support::detail::packed_endian_specific_integral<
|
||||
value_type, TargetEndianness,
|
||||
MaximumAlignment<value_type, MaxAlign>::value> Elf_Off;
|
||||
value_type, TargetEndianness, 2> Elf_Off;
|
||||
};
|
||||
|
||||
// I really don't like doing this, but the alternative is copypasta.
|
||||
#define LLVM_ELF_IMPORT_TYPES(E, M, W) \
|
||||
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Addr \
|
||||
Elf_Addr; \
|
||||
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Off \
|
||||
Elf_Off; \
|
||||
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Half \
|
||||
Elf_Half; \
|
||||
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Word \
|
||||
Elf_Word; \
|
||||
typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Sword \
|
||||
Elf_Sword; \
|
||||
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(E, W) \
|
||||
typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Addr Elf_Addr; \
|
||||
typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Off Elf_Off; \
|
||||
typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Half Elf_Half; \
|
||||
typedef typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Word Elf_Word; \
|
||||
typedef \
|
||||
typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Sword Elf_Sword; \
|
||||
typedef \
|
||||
typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Xword Elf_Xword; \
|
||||
typedef \
|
||||
typename ELFDataTypeTypedefHelper<ELFType<E, W>>::Elf_Sxword Elf_Sxword;
|
||||
|
||||
#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \
|
||||
LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \
|
||||
ELFT::Is64Bits)
|
||||
LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::Is64Bits)
|
||||
|
||||
// Section header.
|
||||
template <class ELFT> struct Elf_Shdr_Base;
|
||||
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, false> > {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Shdr_Base<ELFType<TargetEndianness, false>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
|
||||
Elf_Word sh_name; // Section name (index into string table)
|
||||
Elf_Word sh_type; // Section type (SHT_*)
|
||||
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
|
||||
};
|
||||
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, true> > {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Shdr_Base<ELFType<TargetEndianness, true>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
|
||||
Elf_Word sh_name; // Section name (index into string table)
|
||||
Elf_Word sh_type; // Section type (SHT_*)
|
||||
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 <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, false> > {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Sym_Base<ELFType<TargetEndianness, false>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
|
||||
Elf_Word st_name; // Symbol name (index into string table)
|
||||
Elf_Addr st_value; // Value or address associated with 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
|
||||
};
|
||||
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Sym_Base<ELFType<TargetEndianness, true>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
|
||||
Elf_Word st_name; // Symbol name (index into string table)
|
||||
unsigned char st_info; // Symbol's type and binding attributes
|
||||
unsigned char st_other; // Must be zero; reserved
|
||||
@ -176,6 +154,7 @@ struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > {
|
||||
template <class ELFT>
|
||||
struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
|
||||
using Elf_Sym_Base<ELFT>::st_info;
|
||||
using Elf_Sym_Base<ELFT>::st_shndx;
|
||||
using Elf_Sym_Base<ELFT>::st_other;
|
||||
|
||||
// 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");
|
||||
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
|
||||
@ -267,9 +265,9 @@ struct Elf_Vernaux_Impl {
|
||||
/// table section (.dynamic) look like.
|
||||
template <class ELFT> struct Elf_Dyn_Base;
|
||||
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, false> > {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Dyn_Base<ELFType<TargetEndianness, false>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
|
||||
Elf_Sword d_tag;
|
||||
union {
|
||||
Elf_Word d_val;
|
||||
@ -277,9 +275,9 @@ struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, false> > {
|
||||
} d_un;
|
||||
};
|
||||
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, true> > {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Dyn_Base<ELFType<TargetEndianness, true>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
|
||||
Elf_Sxword d_tag;
|
||||
union {
|
||||
Elf_Xword d_val;
|
||||
@ -300,9 +298,9 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
|
||||
// Elf_Rel: Elf Relocation
|
||||
template <class ELFT, bool isRela> struct Elf_Rel_Base;
|
||||
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Rel_Base<ELFType<TargetEndianness, false>, false> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
|
||||
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
|
||||
|
||||
@ -316,9 +314,9 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> {
|
||||
}
|
||||
};
|
||||
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Rel_Base<ELFType<TargetEndianness, true>, false> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
|
||||
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
|
||||
|
||||
@ -341,9 +339,9 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> {
|
||||
}
|
||||
};
|
||||
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Rel_Base<ELFType<TargetEndianness, false>, true> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
|
||||
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_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>
|
||||
struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Rel_Base<ELFType<TargetEndianness, true>, true> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
|
||||
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_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 <endianness TargetEndianness, std::size_t MaxAlign, bool isRela>
|
||||
struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>,
|
||||
isRela> : Elf_Rel_Base<
|
||||
ELFType<TargetEndianness, MaxAlign, true>, isRela> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
|
||||
template <endianness TargetEndianness, bool isRela>
|
||||
struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, isRela>
|
||||
: Elf_Rel_Base<ELFType<TargetEndianness, true>, isRela> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
|
||||
|
||||
// These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
|
||||
// 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>
|
||||
struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, false>,
|
||||
isRela> : Elf_Rel_Base<
|
||||
ELFType<TargetEndianness, MaxAlign, false>, isRela> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
|
||||
template <endianness TargetEndianness, bool isRela>
|
||||
struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, isRela>
|
||||
: Elf_Rel_Base<ELFType<TargetEndianness, false>, isRela> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
|
||||
|
||||
// These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
|
||||
// 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 <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, false> > {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Phdr_Impl<ELFType<TargetEndianness, false>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
|
||||
Elf_Word p_type; // Type of segment
|
||||
Elf_Off p_offset; // FileOffset where segment is located, in bytes
|
||||
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
|
||||
};
|
||||
|
||||
template <endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
|
||||
template <endianness TargetEndianness>
|
||||
struct Elf_Phdr_Impl<ELFType<TargetEndianness, true>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
|
||||
Elf_Word p_type; // Type of segment
|
||||
Elf_Word p_flags; // Segment flags
|
||||
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>
|
||||
struct Elf_Mips_RegInfo;
|
||||
|
||||
template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Mips_RegInfo<ELFType<TargetEndianness, MaxAlign, false>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
|
||||
template <llvm::support::endianness TargetEndianness>
|
||||
struct Elf_Mips_RegInfo<ELFType<TargetEndianness, false>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
|
||||
Elf_Word ri_gprmask; // bit-mask of used general registers
|
||||
Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
|
||||
Elf_Addr ri_gp_value; // gp register value
|
||||
};
|
||||
|
||||
template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
|
||||
struct Elf_Mips_RegInfo<ELFType<TargetEndianness, MaxAlign, true>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
|
||||
template <llvm::support::endianness TargetEndianness>
|
||||
struct Elf_Mips_RegInfo<ELFType<TargetEndianness, true>> {
|
||||
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
|
||||
Elf_Word ri_gprmask; // bit-mask of used general registers
|
||||
Elf_Word ri_pad; // unused padding field
|
||||
Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
|
||||
|
@ -22,12 +22,15 @@ namespace object {
|
||||
const std::error_category &object_category();
|
||||
|
||||
enum class object_error {
|
||||
success = 0,
|
||||
arch_not_found,
|
||||
// Error code 0 is absent. Use std::error_code() instead.
|
||||
arch_not_found = 1,
|
||||
invalid_file_type,
|
||||
parse_failed,
|
||||
unexpected_eof,
|
||||
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) {
|
||||
|
@ -190,6 +190,8 @@ class MachOObjectFile : public ObjectFile {
|
||||
const char *Ptr; // Where in memory the load command is.
|
||||
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,
|
||||
std::error_code &EC);
|
||||
@ -204,9 +206,8 @@ class MachOObjectFile : public ObjectFile {
|
||||
|
||||
std::error_code getSymbolAddress(DataRefImpl Symb,
|
||||
uint64_t &Res) const override;
|
||||
std::error_code getSymbolAlignment(DataRefImpl Symb,
|
||||
uint32_t &Res) const override;
|
||||
std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override;
|
||||
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
|
||||
uint64_t getSymbolSize(DataRefImpl Symb) const override;
|
||||
std::error_code getSymbolType(DataRefImpl Symb,
|
||||
SymbolRef::Type &Res) const override;
|
||||
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
|
||||
@ -241,11 +242,9 @@ class MachOObjectFile : public ObjectFile {
|
||||
std::error_code
|
||||
getRelocationTypeName(DataRefImpl Rel,
|
||||
SmallVectorImpl<char> &Result) const override;
|
||||
std::error_code
|
||||
getRelocationValueString(DataRefImpl Rel,
|
||||
SmallVectorImpl<char> &Result) const override;
|
||||
std::error_code getRelocationHidden(DataRefImpl Rel,
|
||||
bool &Result) const override;
|
||||
uint8_t getRelocationLength(DataRefImpl Rel) const;
|
||||
|
||||
// MachO specific.
|
||||
std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const;
|
||||
@ -273,10 +272,14 @@ class MachOObjectFile : public ObjectFile {
|
||||
|
||||
dice_iterator begin_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.
|
||||
iterator_range<export_iterator> exports() const;
|
||||
|
||||
|
||||
/// For use examining a trie not in a MachOObjectFile.
|
||||
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;
|
||||
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::section getSection(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::data_in_code_entry getDice(DataRefImpl Rel) const;
|
||||
MachO::mach_header getHeader() const;
|
||||
MachO::mach_header_64 getHeader64() const;
|
||||
const MachO::mach_header &getHeader() const;
|
||||
const MachO::mach_header_64 &getHeader64() const;
|
||||
uint32_t
|
||||
getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC,
|
||||
unsigned Index) const;
|
||||
@ -430,10 +429,15 @@ class MachOObjectFile : public ObjectFile {
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
MachO::mach_header_64 Header64;
|
||||
MachO::mach_header Header;
|
||||
};
|
||||
typedef SmallVector<const char*, 1> SectionList;
|
||||
SectionList Sections;
|
||||
typedef SmallVector<const char*, 1> LibraryList;
|
||||
LibraryList Libraries;
|
||||
LoadCommandList LoadCommands;
|
||||
typedef SmallVector<StringRef, 1> LibraryShortName;
|
||||
mutable LibraryShortName LibrariesShortNames;
|
||||
const char *SymtabLoadCmd;
|
||||
@ -472,7 +476,7 @@ inline std::error_code DiceRef::getOffset(uint32_t &Result) const {
|
||||
static_cast<const MachOObjectFile *>(OwningObject);
|
||||
MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
|
||||
Result = Dice.offset;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
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);
|
||||
MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
|
||||
Result = Dice.length;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
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);
|
||||
MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
|
||||
Result = Dice.kind;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
inline DataRefImpl DiceRef::getRawDataRefImpl() const {
|
||||
|
@ -66,11 +66,6 @@ class RelocationRef {
|
||||
/// This is for display purposes only.
|
||||
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;
|
||||
const ObjectFile *getObjectFile() const;
|
||||
@ -146,8 +141,8 @@ class SymbolRef : public BasicSymbolRef {
|
||||
/// mapped).
|
||||
std::error_code getAddress(uint64_t &Result) const;
|
||||
/// @brief Get the alignment of this symbol as the actual value (not log 2).
|
||||
std::error_code getAlignment(uint32_t &Result) const;
|
||||
std::error_code getSize(uint64_t &Result) const;
|
||||
uint32_t getAlignment() const;
|
||||
uint64_t getSize() const;
|
||||
std::error_code getType(SymbolRef::Type &Result) const;
|
||||
std::error_code getOther(uint8_t &Result) const;
|
||||
|
||||
@ -206,10 +201,8 @@ class ObjectFile : public SymbolicFile {
|
||||
DataRefImpl Symb) const override;
|
||||
virtual std::error_code getSymbolAddress(DataRefImpl Symb,
|
||||
uint64_t &Res) const = 0;
|
||||
virtual std::error_code getSymbolAlignment(DataRefImpl Symb,
|
||||
uint32_t &Res) const;
|
||||
virtual std::error_code getSymbolSize(DataRefImpl Symb,
|
||||
uint64_t &Res) const = 0;
|
||||
virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const;
|
||||
virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0;
|
||||
virtual std::error_code getSymbolType(DataRefImpl Symb,
|
||||
SymbolRef::Type &Res) const = 0;
|
||||
virtual std::error_code getSymbolSection(DataRefImpl Symb,
|
||||
@ -254,13 +247,10 @@ class ObjectFile : public SymbolicFile {
|
||||
virtual std::error_code
|
||||
getRelocationTypeName(DataRefImpl Rel,
|
||||
SmallVectorImpl<char> &Result) const = 0;
|
||||
virtual std::error_code
|
||||
getRelocationValueString(DataRefImpl Rel,
|
||||
SmallVectorImpl<char> &Result) const = 0;
|
||||
virtual std::error_code getRelocationHidden(DataRefImpl Rel,
|
||||
bool &Result) const {
|
||||
Result = false;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
public:
|
||||
@ -334,12 +324,12 @@ inline std::error_code SymbolRef::getAddress(uint64_t &Result) const {
|
||||
return getObject()->getSymbolAddress(getRawDataRefImpl(), Result);
|
||||
}
|
||||
|
||||
inline std::error_code SymbolRef::getAlignment(uint32_t &Result) const {
|
||||
return getObject()->getSymbolAlignment(getRawDataRefImpl(), Result);
|
||||
inline uint32_t SymbolRef::getAlignment() const {
|
||||
return getObject()->getSymbolAlignment(getRawDataRefImpl());
|
||||
}
|
||||
|
||||
inline std::error_code SymbolRef::getSize(uint64_t &Result) const {
|
||||
return getObject()->getSymbolSize(getRawDataRefImpl(), Result);
|
||||
inline uint64_t SymbolRef::getSize() const {
|
||||
return getObject()->getSymbolSize(getRawDataRefImpl());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
inline std::error_code
|
||||
RelocationRef::getValueString(SmallVectorImpl<char> &Result) const {
|
||||
return OwningObject->getRelocationValueString(RelocationPimpl, Result);
|
||||
}
|
||||
|
||||
inline std::error_code RelocationRef::getHidden(bool &Result) const {
|
||||
return OwningObject->getRelocationHidden(RelocationPimpl, Result);
|
||||
}
|
||||
|
@ -19,9 +19,11 @@
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
@ -52,6 +54,8 @@ class RelocVisitor {
|
||||
return visitELF(RelocType, R, Value);
|
||||
if (isa<COFFObjectFile>(ObjToVisit))
|
||||
return visitCOFF(RelocType, R, Value);
|
||||
if (isa<MachOObjectFile>(ObjToVisit))
|
||||
return visitMachO(RelocType, R, Value);
|
||||
|
||||
HasError = true;
|
||||
return RelocToApply();
|
||||
@ -221,6 +225,20 @@ class RelocVisitor {
|
||||
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) {
|
||||
const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile());
|
||||
DataRefImpl DRI = R.getRawDataRefImpl();
|
||||
@ -252,6 +270,12 @@ class RelocVisitor {
|
||||
Obj->getRelocationAddend(DRI, Addend);
|
||||
return Addend;
|
||||
}
|
||||
|
||||
uint8_t getLengthMachO64(RelocationRef R) {
|
||||
const MachOObjectFile *Obj = cast<MachOObjectFile>(R.getObjectFile());
|
||||
return Obj->getRelocationLength(R.getRawDataRefImpl());
|
||||
}
|
||||
|
||||
/// Operations
|
||||
|
||||
/// 386-ELF
|
||||
@ -413,6 +437,13 @@ class RelocVisitor {
|
||||
RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
|
||||
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;
|
||||
};
|
||||
|
||||
enum SymbolFlags {
|
||||
SF_TypeMask = 0x0000FFFF,
|
||||
SF_TypeShift = 0,
|
||||
|
||||
SF_ClassMask = 0x00FF0000,
|
||||
SF_ClassShift = 16,
|
||||
|
||||
SF_WeakExternal = 0x01000000
|
||||
};
|
||||
|
||||
enum SymbolSectionNumber : int32_t {
|
||||
IMAGE_SYM_DEBUG = -2,
|
||||
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
|
||||
// inherit from a class, we do so. This makes us exactly compatible with the
|
||||
// object in all cases that it is used.
|
||||
// Define how to hold a class type object, such as a string.
|
||||
// Originally this code inherited from std::vector. In transitioning to a new
|
||||
// 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>
|
||||
class list_storage<DataType, bool> : public std::vector<DataType> {
|
||||
// FIXME: Reduce this API to a more narrow subset of std::vector
|
||||
//
|
||||
template <class DataType> class list_storage<DataType, bool> {
|
||||
std::vector<DataType> Storage;
|
||||
|
||||
public:
|
||||
template <class T> void addValue(const T &V) {
|
||||
std::vector<DataType>::push_back(V);
|
||||
typedef typename std::vector<DataType>::iterator iterator;
|
||||
|
||||
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.
|
||||
//
|
||||
template <class DataType, class Storage = bool,
|
||||
template <class DataType, class StorageClass = bool,
|
||||
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;
|
||||
ParserClass Parser;
|
||||
|
||||
@ -1319,7 +1376,7 @@ class list : public Option, public list_storage<DataType, Storage> {
|
||||
typename ParserClass::parser_data_type();
|
||||
if (Parser.parse(*this, ArgName, Arg, Val))
|
||||
return true; // Parse Error!
|
||||
list_storage<DataType, Storage>::addValue(Val);
|
||||
list_storage<DataType, StorageClass>::addValue(Val);
|
||||
setPosition(pos);
|
||||
Positions.push_back(pos);
|
||||
return false;
|
||||
|
@ -350,19 +350,6 @@
|
||||
# define LLVM_ADDRESS_SANITIZER_BUILD 0
|
||||
#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
|
||||
/// stripped from debug builds.
|
||||
// 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_16_X, 84)
|
||||
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
|
||||
/// 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) &&
|
||||
"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
|
||||
/// 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;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,10 @@
|
||||
#ifndef 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 {
|
||||
class StringRef;
|
||||
|
||||
@ -28,13 +32,16 @@ namespace ARM {
|
||||
// FPU names.
|
||||
enum FPUKind {
|
||||
FK_INVALID = 0,
|
||||
FK_NONE,
|
||||
FK_VFP,
|
||||
FK_VFPV2,
|
||||
FK_VFPV3,
|
||||
FK_VFPV3_D16,
|
||||
FK_VFPV4,
|
||||
FK_VFPV4_D16,
|
||||
FK_FPV4_SP_D16,
|
||||
FK_FPV5_D16,
|
||||
FK_FPV5_SP_D16,
|
||||
FK_FP_ARMV8,
|
||||
FK_NEON,
|
||||
FK_NEON_VFPV4,
|
||||
@ -44,6 +51,20 @@ namespace ARM {
|
||||
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.
|
||||
enum ArchKind {
|
||||
AK_INVALID = 0,
|
||||
@ -53,34 +74,34 @@ namespace ARM {
|
||||
AK_ARMV3M,
|
||||
AK_ARMV4,
|
||||
AK_ARMV4T,
|
||||
AK_ARMV5,
|
||||
AK_ARMV5T,
|
||||
AK_ARMV5TE,
|
||||
AK_ARMV5TEJ,
|
||||
AK_ARMV6,
|
||||
AK_ARMV6J,
|
||||
AK_ARMV6K,
|
||||
AK_ARMV6T2,
|
||||
AK_ARMV6Z,
|
||||
AK_ARMV6ZK,
|
||||
AK_ARMV6M,
|
||||
AK_ARMV7,
|
||||
AK_ARMV6SM,
|
||||
AK_ARMV7A,
|
||||
AK_ARMV7R,
|
||||
AK_ARMV7M,
|
||||
AK_ARMV7EM,
|
||||
AK_ARMV8A,
|
||||
AK_ARMV8_1A,
|
||||
// Non-standard Arch names.
|
||||
AK_IWMMXT,
|
||||
AK_IWMMXT2,
|
||||
AK_XSCALE,
|
||||
AK_ARMV5,
|
||||
AK_ARMV5E,
|
||||
AK_ARMV5TEJ,
|
||||
AK_ARMV6SM,
|
||||
AK_ARMV6J,
|
||||
AK_ARMV6HL,
|
||||
AK_ARMV7,
|
||||
AK_ARMV7L,
|
||||
AK_ARMV7HL,
|
||||
AK_ARMV7S,
|
||||
AK_ARMV7EM,
|
||||
AK_LAST
|
||||
};
|
||||
|
||||
@ -92,8 +113,15 @@ namespace ARM {
|
||||
AEK_FP,
|
||||
AEK_HWDIV,
|
||||
AEK_MP,
|
||||
AEK_SIMD,
|
||||
AEK_SEC,
|
||||
AEK_VIRT,
|
||||
// Unsupported extensions.
|
||||
AEK_OS,
|
||||
AEK_IWMMXT,
|
||||
AEK_IWMMXT2,
|
||||
AEK_MAVERICK,
|
||||
AEK_XSCALE,
|
||||
AEK_LAST
|
||||
};
|
||||
|
||||
@ -132,9 +160,16 @@ class ARMTargetParser {
|
||||
|
||||
// Information by ID
|
||||
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 unsigned getArchDefaultCPUArch(unsigned ArchKind);
|
||||
static const char * getArchDefaultCPUName(unsigned ArchKind);
|
||||
static unsigned getArchAttr(unsigned ArchKind);
|
||||
static const char * getCPUAttr(unsigned ArchKind);
|
||||
static const char * getSubArch(unsigned ArchKind);
|
||||
static const char * getArchExtName(unsigned ArchExtKind);
|
||||
static const char * getDefaultCPU(StringRef Arch);
|
||||
|
||||
|
@ -91,7 +91,7 @@ class Target {
|
||||
typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch);
|
||||
|
||||
typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI,
|
||||
StringRef TT);
|
||||
const Triple &TT);
|
||||
typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, Reloc::Model RM,
|
||||
CodeModel::Model CM,
|
||||
CodeGenOpt::Level OL);
|
||||
@ -287,15 +287,15 @@ class Target {
|
||||
/// createMCAsmInfo - Create a MCAsmInfo implementation for the specified
|
||||
/// 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
|
||||
/// either the target triple from the module, or the target triple of the
|
||||
/// host if that does not exist.
|
||||
MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI,
|
||||
StringRef Triple) const {
|
||||
StringRef TheTriple) const {
|
||||
if (!MCAsmInfoCtorFn)
|
||||
return nullptr;
|
||||
return MCAsmInfoCtorFn(MRI, Triple);
|
||||
return MCAsmInfoCtorFn(MRI, Triple(TheTriple));
|
||||
}
|
||||
|
||||
/// createMCCodeGenInfo - Create a MCCodeGenInfo implementation.
|
||||
@ -889,7 +889,8 @@ template <class MCAsmInfoImpl> struct RegisterMCAsmInfo {
|
||||
}
|
||||
|
||||
private:
|
||||
static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/, StringRef TT) {
|
||||
static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/,
|
||||
const Triple &TT) {
|
||||
return new MCAsmInfoImpl(TT);
|
||||
}
|
||||
};
|
||||
|
@ -1090,6 +1090,9 @@ class Input : public IO {
|
||||
bool setCurrentDocument();
|
||||
bool nextDocument();
|
||||
|
||||
/// Returns the current node that's being parsed by the YAML Parser.
|
||||
const Node *getCurrentNode() const;
|
||||
|
||||
private:
|
||||
llvm::SourceMgr SrcMgr; // must be before Strm
|
||||
std::unique_ptr<llvm::yaml::Stream> Strm;
|
||||
@ -1111,7 +1114,7 @@ class Input : public IO {
|
||||
///
|
||||
class Output : public IO {
|
||||
public:
|
||||
Output(llvm::raw_ostream &, void *Ctxt=nullptr);
|
||||
Output(llvm::raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
|
||||
~Output() override;
|
||||
|
||||
bool outputting() override;
|
||||
@ -1167,6 +1170,7 @@ class Output : public IO {
|
||||
};
|
||||
|
||||
llvm::raw_ostream &Out;
|
||||
int WrapColumn;
|
||||
SmallVector<InState, 8> StateStack;
|
||||
int Column;
|
||||
int ColumnAtFlowStart;
|
||||
|
@ -17,48 +17,20 @@
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// RecTy subclasses.
|
||||
class BitRecTy;
|
||||
class BitsRecTy;
|
||||
class IntRecTy;
|
||||
class StringRecTy;
|
||||
class ListRecTy;
|
||||
class DagRecTy;
|
||||
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.
|
||||
struct MultiClass;
|
||||
class Record;
|
||||
class RecordVal;
|
||||
struct MultiClass;
|
||||
class RecordKeeper;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -81,12 +53,11 @@ class RecTy {
|
||||
private:
|
||||
RecTyKind Kind;
|
||||
std::unique_ptr<ListRecTy> ListTy;
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
RecTyKind getRecTyKind() const { return Kind; }
|
||||
|
||||
RecTy(RecTyKind K) : Kind(K), ListTy(nullptr) {}
|
||||
RecTy(RecTyKind K) : Kind(K) {}
|
||||
virtual ~RecTy() {}
|
||||
|
||||
virtual std::string getAsString() const = 0;
|
||||
@ -95,40 +66,10 @@ class RecTy {
|
||||
|
||||
/// typeIsConvertibleTo - Return true if all values of 'this' type can be
|
||||
/// 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>.
|
||||
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) {
|
||||
@ -149,20 +90,9 @@ class BitRecTy : public RecTy {
|
||||
|
||||
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"; }
|
||||
|
||||
bool typeIsConvertibleTo(const RecTy *RHS) const override {
|
||||
return RHS->baseClassOf(this);
|
||||
}
|
||||
bool baseClassOf(const RecTy*) const override;
|
||||
bool typeIsConvertibleTo(const RecTy *RHS) const override;
|
||||
};
|
||||
|
||||
/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
|
||||
@ -180,19 +110,9 @@ class BitsRecTy : public RecTy {
|
||||
|
||||
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;
|
||||
|
||||
bool typeIsConvertibleTo(const RecTy *RHS) const override {
|
||||
return RHS->baseClassOf(this);
|
||||
}
|
||||
bool baseClassOf(const RecTy*) const override;
|
||||
bool typeIsConvertibleTo(const RecTy *RHS) const override;
|
||||
};
|
||||
|
||||
/// IntRecTy - 'int' - Represent an integer value of no particular size
|
||||
@ -208,20 +128,9 @@ class IntRecTy : public RecTy {
|
||||
|
||||
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"; }
|
||||
|
||||
bool typeIsConvertibleTo(const RecTy *RHS) const override {
|
||||
return RHS->baseClassOf(this);
|
||||
}
|
||||
|
||||
bool baseClassOf(const RecTy*) const override;
|
||||
bool typeIsConvertibleTo(const RecTy *RHS) const override;
|
||||
};
|
||||
|
||||
/// StringRecTy - 'string' - Represent an string value
|
||||
@ -237,18 +146,7 @@ class StringRecTy : public RecTy {
|
||||
|
||||
static StringRecTy *get() { return &Shared; }
|
||||
|
||||
using RecTy::convertValue;
|
||||
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);
|
||||
}
|
||||
std::string getAsString() const override;
|
||||
};
|
||||
|
||||
/// 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(); }
|
||||
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;
|
||||
|
||||
bool typeIsConvertibleTo(const RecTy *RHS) const override {
|
||||
return RHS->baseClassOf(this);
|
||||
}
|
||||
|
||||
bool baseClassOf(const RecTy*) const override;
|
||||
bool typeIsConvertibleTo(const RecTy *RHS) const override;
|
||||
};
|
||||
|
||||
/// DagRecTy - 'dag' - Represent a dag fragment
|
||||
@ -294,18 +183,7 @@ class DagRecTy : public RecTy {
|
||||
|
||||
static DagRecTy *get() { return &Shared; }
|
||||
|
||||
using RecTy::convertValue;
|
||||
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);
|
||||
}
|
||||
std::string getAsString() const override;
|
||||
};
|
||||
|
||||
/// RecordRecTy - '[classname]' - Represent an instance of a class, such as:
|
||||
@ -325,17 +203,9 @@ class RecordRecTy : public RecTy {
|
||||
|
||||
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;
|
||||
|
||||
bool typeIsConvertibleTo(const RecTy *RHS) const override {
|
||||
return RHS->baseClassOf(this);
|
||||
}
|
||||
bool baseClassOf(const RecTy*) const override;
|
||||
bool typeIsConvertibleTo(const RecTy *RHS) const override;
|
||||
};
|
||||
|
||||
/// resolveTypes - Find a common type that T1 and T2 convert to.
|
||||
@ -418,10 +288,8 @@ class Init {
|
||||
/// invokes print on stderr.
|
||||
void dump() const;
|
||||
|
||||
/// convertInitializerTo - This virtual function is a simple call-back
|
||||
/// function that should be overridden to call the appropriate
|
||||
/// RecTy::convertValue method.
|
||||
///
|
||||
/// convertInitializerTo - This virtual function converts to the appropriate
|
||||
/// Init based on the passed in type.
|
||||
virtual Init *convertInitializerTo(RecTy *Ty) const = 0;
|
||||
|
||||
/// convertInitializerBitRange - This method is used to implement the bitrange
|
||||
@ -511,6 +379,8 @@ class TypedInit : public Init {
|
||||
}
|
||||
RecTy *getType() const { return Ty; }
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
||||
Init *
|
||||
convertInitializerBitRange(const std::vector<unsigned> &Bits) const override;
|
||||
Init *
|
||||
@ -535,7 +405,6 @@ class UnsetInit : public Init {
|
||||
UnsetInit() : Init(IK_UnsetInit) {}
|
||||
UnsetInit(const UnsetInit &) = delete;
|
||||
UnsetInit &operator=(const UnsetInit &Other) = delete;
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
static bool classof(const Init *I) {
|
||||
@ -543,9 +412,7 @@ class UnsetInit : public Init {
|
||||
}
|
||||
static UnsetInit *get();
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override {
|
||||
return Ty->convertValue(const_cast<UnsetInit *>(this));
|
||||
}
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
||||
Init *getBit(unsigned Bit) const override {
|
||||
return const_cast<UnsetInit*>(this);
|
||||
@ -563,7 +430,6 @@ class BitInit : public Init {
|
||||
explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {}
|
||||
BitInit(const BitInit &Other) = delete;
|
||||
BitInit &operator=(BitInit &Other) = delete;
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
static bool classof(const Init *I) {
|
||||
@ -573,9 +439,7 @@ class BitInit : public Init {
|
||||
|
||||
bool getValue() const { return Value; }
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override {
|
||||
return Ty->convertValue(const_cast<BitInit *>(this));
|
||||
}
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
||||
Init *getBit(unsigned Bit) const override {
|
||||
assert(Bit < 1 && "Bit index out of range!");
|
||||
@ -608,9 +472,7 @@ class BitsInit : public TypedInit, public FoldingSetNode {
|
||||
|
||||
unsigned getNumBits() const { return Bits.size(); }
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override {
|
||||
return Ty->convertValue(const_cast<BitsInit *>(this));
|
||||
}
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
Init *
|
||||
convertInitializerBitRange(const std::vector<unsigned> &Bits) const override;
|
||||
|
||||
@ -661,9 +523,7 @@ class IntInit : public TypedInit {
|
||||
|
||||
int64_t getValue() const { return Value; }
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override {
|
||||
return Ty->convertValue(const_cast<IntInit *>(this));
|
||||
}
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
Init *
|
||||
convertInitializerBitRange(const std::vector<unsigned> &Bits) const override;
|
||||
|
||||
@ -692,7 +552,6 @@ class StringInit : public TypedInit {
|
||||
|
||||
StringInit(const StringInit &Other) = delete;
|
||||
StringInit &operator=(const StringInit &Other) = delete;
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
static bool classof(const Init *I) {
|
||||
@ -702,9 +561,7 @@ class StringInit : public TypedInit {
|
||||
|
||||
const std::string &getValue() const { return Value; }
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override {
|
||||
return Ty->convertValue(const_cast<StringInit *>(this));
|
||||
}
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
||||
std::string getAsString() 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;
|
||||
|
||||
unsigned getSize() const { return Values.size(); }
|
||||
Init *getElement(unsigned i) const {
|
||||
assert(i < Values.size() && "List element index out of range!");
|
||||
return Values[i];
|
||||
@ -757,9 +613,7 @@ class ListInit : public TypedInit, public FoldingSetNode {
|
||||
Init *
|
||||
convertInitListSlice(const std::vector<unsigned> &Elements) const override;
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override {
|
||||
return Ty->convertValue(const_cast<ListInit *>(this));
|
||||
}
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
||||
/// resolveReferences - This method is used by classes that refer to other
|
||||
/// 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; }
|
||||
|
||||
inline const_iterator begin() const { return Values.begin(); }
|
||||
inline const_iterator end () const { return Values.end(); }
|
||||
const_iterator begin() const { return Values.begin(); }
|
||||
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
|
||||
/// 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
|
||||
virtual OpInit *clone(std::vector<Init *> &Operands) const = 0;
|
||||
|
||||
virtual int getNumOperands() const = 0;
|
||||
virtual Init *getOperand(int i) const = 0;
|
||||
virtual unsigned getNumOperands() const = 0;
|
||||
virtual Init *getOperand(unsigned i) const = 0;
|
||||
|
||||
// Fold - If possible, fold this to a simpler init. Return this if not
|
||||
// possible to fold.
|
||||
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,
|
||||
unsigned Elt) const override;
|
||||
|
||||
@ -851,8 +702,8 @@ class UnOpInit : public OpInit {
|
||||
return UnOpInit::get(getOpcode(), *Operands.begin(), getType());
|
||||
}
|
||||
|
||||
int getNumOperands() const override { return 1; }
|
||||
Init *getOperand(int i) const override {
|
||||
unsigned getNumOperands() const override { return 1; }
|
||||
Init *getOperand(unsigned i) const override {
|
||||
assert(i == 0 && "Invalid operand id for unary operator");
|
||||
return getOperand();
|
||||
}
|
||||
@ -899,13 +750,12 @@ class BinOpInit : public OpInit {
|
||||
return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType());
|
||||
}
|
||||
|
||||
int getNumOperands() const override { return 2; }
|
||||
Init *getOperand(int i) const override {
|
||||
assert((i == 0 || i == 1) && "Invalid operand id for binary operator");
|
||||
if (i == 0) {
|
||||
return getLHS();
|
||||
} else {
|
||||
return getRHS();
|
||||
unsigned getNumOperands() const override { return 2; }
|
||||
Init *getOperand(unsigned i) const override {
|
||||
switch (i) {
|
||||
default: llvm_unreachable("Invalid operand id for binary operator");
|
||||
case 0: return getLHS();
|
||||
case 1: return getRHS();
|
||||
}
|
||||
}
|
||||
|
||||
@ -955,16 +805,13 @@ class TernOpInit : public OpInit {
|
||||
getType());
|
||||
}
|
||||
|
||||
int getNumOperands() const override { return 3; }
|
||||
Init *getOperand(int i) const override {
|
||||
assert((i == 0 || i == 1 || i == 2) &&
|
||||
"Invalid operand id for ternary operator");
|
||||
if (i == 0) {
|
||||
return getLHS();
|
||||
} else if (i == 1) {
|
||||
return getMHS();
|
||||
} else {
|
||||
return getRHS();
|
||||
unsigned getNumOperands() const override { return 3; }
|
||||
Init *getOperand(unsigned i) const override {
|
||||
switch (i) {
|
||||
default: llvm_unreachable("Invalid operand id for ternary operator");
|
||||
case 0: return getLHS();
|
||||
case 1: return getMHS();
|
||||
case 2: return getRHS();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1004,10 +851,6 @@ class VarInit : public TypedInit {
|
||||
static VarInit *get(const std::string &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;
|
||||
Init *getNameInit() const { return VarName; }
|
||||
std::string getNameInitAsString() const {
|
||||
@ -1056,9 +899,7 @@ class VarBitInit : public Init {
|
||||
}
|
||||
static VarBitInit *get(TypedInit *T, unsigned B);
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override {
|
||||
return Ty->convertValue(const_cast<VarBitInit *>(this));
|
||||
}
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
||||
Init *getBitVar() const override { return TI; }
|
||||
unsigned getBitNum() const override { return Bit; }
|
||||
@ -1095,10 +936,6 @@ class VarListElementInit : public TypedInit {
|
||||
}
|
||||
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; }
|
||||
unsigned getElementNum() const { return Element; }
|
||||
|
||||
@ -1131,9 +968,7 @@ class DefInit : public TypedInit {
|
||||
}
|
||||
static DefInit *get(Record*);
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override {
|
||||
return Ty->convertValue(const_cast<DefInit *>(this));
|
||||
}
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
||||
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 Init *FN);
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override {
|
||||
return Ty->convertValue(const_cast<FieldInit *>(this));
|
||||
}
|
||||
|
||||
Init *getBit(unsigned Bit) const override;
|
||||
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
@ -1228,9 +1059,7 @@ class DagInit : public TypedInit, public FoldingSetNode {
|
||||
|
||||
void Profile(FoldingSetNodeID &ID) const;
|
||||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override {
|
||||
return Ty->convertValue(const_cast<DagInit *>(this));
|
||||
}
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
||||
Init *getOperator() const { return Val; }
|
||||
|
||||
@ -1280,22 +1109,21 @@ class DagInit : public TypedInit, public FoldingSetNode {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class RecordVal {
|
||||
Init *Name;
|
||||
PointerIntPair<Init *, 1, bool> NameAndPrefix;
|
||||
RecTy *Ty;
|
||||
unsigned Prefix;
|
||||
Init *Value;
|
||||
|
||||
public:
|
||||
RecordVal(Init *N, RecTy *T, unsigned P);
|
||||
RecordVal(const std::string &N, RecTy *T, unsigned P);
|
||||
RecordVal(Init *N, RecTy *T, bool P);
|
||||
RecordVal(const std::string &N, RecTy *T, bool P);
|
||||
|
||||
const std::string &getName() const;
|
||||
const Init *getNameInit() const { return Name; }
|
||||
const Init *getNameInit() const { return NameAndPrefix.getPointer(); }
|
||||
std::string getNameInitAsString() const {
|
||||
return getNameInit()->getAsUnquotedString();
|
||||
}
|
||||
|
||||
unsigned getPrefix() const { return Prefix; }
|
||||
bool getPrefix() const { return NameAndPrefix.getInt(); }
|
||||
RecTy *getType() const { return Ty; }
|
||||
Init *getValue() const { return Value; }
|
||||
|
||||
@ -1344,7 +1172,7 @@ class Record {
|
||||
// def Def : Class<Struct<i>>;
|
||||
//
|
||||
// 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
|
||||
// resolve them later as soon as the multiclass is instantiated.
|
||||
bool ResolveFirst;
|
||||
@ -1354,13 +1182,6 @@ class Record {
|
||||
|
||||
public:
|
||||
// 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,
|
||||
bool Anonymous = false) :
|
||||
ID(LastID++), Name(N), Locs(locs.begin(), locs.end()),
|
||||
@ -1368,6 +1189,10 @@ class Record {
|
||||
ResolveFirst(false) {
|
||||
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
|
||||
// ID number. All other fields can be copied normally.
|
||||
@ -1406,8 +1231,8 @@ class Record {
|
||||
ArrayRef<SMRange> getSuperClassRanges() const { return SuperClassRanges; }
|
||||
|
||||
bool isTemplateArg(Init *Name) const {
|
||||
for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
|
||||
if (TemplateArgs[i] == Name) return true;
|
||||
for (Init *TA : TemplateArgs)
|
||||
if (TA == Name) return true;
|
||||
return false;
|
||||
}
|
||||
bool isTemplateArg(StringRef Name) const {
|
||||
@ -1415,16 +1240,16 @@ class Record {
|
||||
}
|
||||
|
||||
const RecordVal *getValue(const Init *Name) const {
|
||||
for (unsigned i = 0, e = Values.size(); i != e; ++i)
|
||||
if (Values[i].getNameInit() == Name) return &Values[i];
|
||||
for (const RecordVal &Val : Values)
|
||||
if (Val.getNameInit() == Name) return &Val;
|
||||
return nullptr;
|
||||
}
|
||||
const RecordVal *getValue(StringRef Name) const {
|
||||
return getValue(StringInit::get(Name));
|
||||
}
|
||||
RecordVal *getValue(const Init *Name) {
|
||||
for (unsigned i = 0, e = Values.size(); i != e; ++i)
|
||||
if (Values[i].getNameInit() == Name) return &Values[i];
|
||||
for (RecordVal &Val : Values)
|
||||
if (Val.getNameInit() == Name) return &Val;
|
||||
return nullptr;
|
||||
}
|
||||
RecordVal *getValue(StringRef Name) {
|
||||
@ -1465,15 +1290,15 @@ class Record {
|
||||
}
|
||||
|
||||
bool isSubClassOf(const Record *R) const {
|
||||
for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
|
||||
if (SuperClasses[i] == R)
|
||||
for (const Record *SC : SuperClasses)
|
||||
if (SC == R)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSubClassOf(StringRef Name) const {
|
||||
for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
|
||||
if (SuperClasses[i]->getNameInitAsString() == Name)
|
||||
for (const Record *SC : SuperClasses)
|
||||
if (SC->getNameInitAsString() == Name)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@ -1523,7 +1348,7 @@ class Record {
|
||||
|
||||
/// Return true if the named field is unset.
|
||||
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
|
||||
@ -1675,7 +1500,6 @@ struct LessRecordFieldName {
|
||||
};
|
||||
|
||||
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'; }
|
||||
|
||||
struct RecordParts {
|
||||
|
@ -47,9 +47,10 @@
|
||||
#ifndef LLVM_TABLEGEN_SETTHEORY_H
|
||||
#define LLVM_TABLEGEN_SETTHEORY_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
@ -58,7 +59,6 @@ namespace llvm {
|
||||
class DagInit;
|
||||
class Init;
|
||||
class Record;
|
||||
class RecordKeeper;
|
||||
|
||||
class SetTheory {
|
||||
public:
|
||||
|
@ -381,6 +381,7 @@ class Instruction {
|
||||
bit hasPostISelHook = 0; // To be *adjusted* after isel by target hook.
|
||||
bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains?
|
||||
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 hasExtraSrcRegAllocReq = 0; // Sources 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
|
||||
/// 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:
|
||||
/// (outs R32:$dst), (ins R32:$src1, R32:$src2) or something similar.
|
||||
def ops;
|
||||
|
@ -711,20 +711,22 @@ class TargetInstrInfo : public MCInstrInfo {
|
||||
/// Target-dependent implementation for foldMemoryOperand.
|
||||
/// Target-independent code in foldMemoryOperand will
|
||||
/// take care of adding a MachineMemOperand to the newly created instruction.
|
||||
virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF,
|
||||
MachineInstr *MI,
|
||||
ArrayRef<unsigned> Ops,
|
||||
int FrameIndex) const {
|
||||
/// The instruction and any auxiliary instructions necessary will be inserted
|
||||
/// at InsertPt.
|
||||
virtual MachineInstr *foldMemoryOperandImpl(
|
||||
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
|
||||
MachineBasicBlock::iterator InsertPt, int FrameIndex) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Target-dependent implementation for foldMemoryOperand.
|
||||
/// Target-independent code in foldMemoryOperand will
|
||||
/// take care of adding a MachineMemOperand to the newly created instruction.
|
||||
virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF,
|
||||
MachineInstr *MI,
|
||||
ArrayRef<unsigned> Ops,
|
||||
MachineInstr *LoadMI) const {
|
||||
/// The instruction and any auxiliary instructions necessary will be inserted
|
||||
/// at InsertPt.
|
||||
virtual MachineInstr *foldMemoryOperandImpl(
|
||||
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
|
||||
MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1431,7 +1431,8 @@ class TargetLoweringBase {
|
||||
/// load/store.
|
||||
virtual bool GetAddrModeArguments(IntrinsicInst * /*I*/,
|
||||
SmallVectorImpl<Value*> &/*Ops*/,
|
||||
Type *&/*AccessTy*/) const {
|
||||
Type *&/*AccessTy*/,
|
||||
unsigned AddrSpace = 0) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1456,7 +1457,12 @@ class TargetLoweringBase {
|
||||
/// 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
|
||||
/// 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
|
||||
/// 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 not supported, it returns a negative value.
|
||||
/// 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.
|
||||
if (isLegalAddressingMode(AM, Ty)) return 0;
|
||||
if (isLegalAddressingMode(AM, Ty, AS))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifndef LLVM_TARGET_TARGETOPTIONS_H
|
||||
#define LLVM_TARGET_TARGETOPTIONS_H
|
||||
|
||||
#include "llvm/Target/TargetRecip.h"
|
||||
#include "llvm/MC/MCTargetOptions.h"
|
||||
#include <string>
|
||||
|
||||
@ -72,7 +73,8 @@ namespace llvm {
|
||||
CompressDebugSections(false), FunctionSections(false),
|
||||
DataSections(false), UniqueSectionNames(true), TrapUnreachable(false),
|
||||
TrapFuncName(), FloatABIType(FloatABI::Default),
|
||||
AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),
|
||||
AllowFPOpFusion(FPOpFusion::Standard), Reciprocals(TargetRecip()),
|
||||
JTType(JumpTable::Single),
|
||||
ThreadModel(ThreadModel::POSIX) {}
|
||||
|
||||
/// PrintMachineCode - This flag is enabled when the -print-machineinstrs
|
||||
@ -206,6 +208,9 @@ namespace llvm {
|
||||
/// the value of this option.
|
||||
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
|
||||
/// create for functions that have the jumptable attribute.
|
||||
JumpTable::JumpTableType JTType;
|
||||
@ -240,6 +245,7 @@ inline bool operator==(const TargetOptions &LHS,
|
||||
ARE_EQUAL(TrapFuncName) &&
|
||||
ARE_EQUAL(FloatABIType) &&
|
||||
ARE_EQUAL(AllowFPOpFusion) &&
|
||||
ARE_EQUAL(Reciprocals) &&
|
||||
ARE_EQUAL(JTType) &&
|
||||
ARE_EQUAL(ThreadModel) &&
|
||||
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
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <functional>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BasicBlockPass;
|
||||
class Function;
|
||||
class FunctionPass;
|
||||
class ModulePass;
|
||||
class Pass;
|
||||
@ -152,7 +154,14 @@ Pass *createLoopInterchangePass();
|
||||
//
|
||||
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,
|
||||
// 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
|
||||
// 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