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

r239412.
This commit is contained in:
Dimitry Andric 2015-06-10 19:12:52 +00:00
commit 97bc6c731e
710 changed files with 28231 additions and 18945 deletions

View File

@ -997,6 +997,13 @@ unsigned LLVMCountStructElementTypes(LLVMTypeRef StructTy);
*/
void LLVMGetStructElementTypes(LLVMTypeRef StructTy, LLVMTypeRef *Dest);
/**
* 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.
*

View File

@ -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

View File

@ -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.

View File

@ -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; }

View File

@ -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);

View File

@ -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();

View File

@ -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.

View File

@ -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();
}

View File

@ -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)

View File

@ -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.
///

View File

@ -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);
};

View File

@ -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");

View File

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

View File

@ -75,12 +75,12 @@ class PHITransAddr {
bool IsPotentiallyPHITranslatable() const;
/// 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.

View File

@ -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);

View File

@ -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;

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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;

View File

@ -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
};

View File

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

View File

@ -121,7 +121,7 @@ class GCFunctionInfo {
/// label just prior to the safe point (if the code generator is using
/// 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.

View File

@ -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.

View File

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

View File

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

View File

@ -256,11 +256,6 @@ class MachineFrameInfo {
/// Not null, if shrink-wrapping found a better place for the epilogue.
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

View File

@ -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.
///

View File

@ -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);
}

View File

@ -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;

View File

@ -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();

View File

@ -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);

View File

@ -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

View File

@ -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;
};
}

View File

@ -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;

View File

@ -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)),

View File

@ -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));
}
};

View File

@ -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,

View File

@ -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);
}

View File

@ -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],

View File

@ -3372,10 +3372,40 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty],
[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]>;

View File

@ -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

View File

@ -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.
///

View File

@ -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&);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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.
///

View File

@ -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);
}

View File

@ -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,

View File

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

View File

@ -21,17 +21,17 @@ class MCFixup;
class MCFragment;
class 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,

View File

@ -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;

View File

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

View File

@ -46,7 +46,7 @@ class MCExpr {
MCExpr(const MCExpr&) = delete;
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;

View File

@ -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);

View File

@ -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 {

View File

@ -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
//===--------------------------------------------------------------------===//

View File

@ -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

View File

@ -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() {

View File

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

View File

@ -27,15 +27,11 @@ class MCMachObjectTargetWriter {
const unsigned Is64Bit : 1;
const 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.
///

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

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

View File

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

View File

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

View File

@ -50,9 +50,9 @@ class MCWinCOFFStreamer : public MCObjectStreamer {
void EmitCOFFSymbolStorageClass(int StorageClass) override;
void 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,

View File

@ -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,

View File

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

View File

@ -613,7 +613,7 @@ class COFFObjectFile : public ObjectFile {
StringRef &Res) const override;
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;

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -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) {

View File

@ -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 {

View File

@ -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);
}

View File

@ -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);
}
};
}

View File

@ -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,

View File

@ -1284,24 +1284,81 @@ template <class DataType, class StorageClass> class list_storage {
}
};
// Define how to hold a class type object, such as a string. Since we can
// 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;

View File

@ -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.

View File

@ -90,3 +90,11 @@ ELF_RELOC(R_HEX_IE_GOT_11_X, 82)
ELF_RELOC(R_HEX_TPREL_32_6_X, 83)
ELF_RELOC(R_HEX_TPREL_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)

View File

@ -562,7 +562,7 @@ inline uint64_t MinAlign(uint64_t A, uint64_t B) {
///
/// Alignment should be a power of two. This method rounds up, so
/// 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;
}

View File

@ -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);

View File

@ -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);
}
};

View File

@ -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;

View File

@ -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 {

View File

@ -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:

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

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

View File

@ -16,10 +16,12 @@
#define LLVM_TRANSFORMS_SCALAR_H
#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