diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-01-14 20:04:09 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-01-14 20:04:09 +0000 |
commit | 86d685a17b1e4f8b57c4d5bd48e0a5429f3028e3 (patch) | |
tree | dfd6da3109a33a451fb87ff4ca62c59945430ad5 /gnu/llvm/lib | |
parent | ca82c85029ae0befb17bc14a4faa9f3d51dd72b3 (diff) |
Merge LLVM 3.9.1
Diffstat (limited to 'gnu/llvm/lib')
185 files changed, 270 insertions, 18834 deletions
diff --git a/gnu/llvm/lib/Analysis/CFLAliasAnalysis.cpp b/gnu/llvm/lib/Analysis/CFLAliasAnalysis.cpp deleted file mode 100644 index 4843ed6587a..00000000000 --- a/gnu/llvm/lib/Analysis/CFLAliasAnalysis.cpp +++ /dev/null @@ -1,1119 +0,0 @@ -//===- CFLAliasAnalysis.cpp - CFL-Based Alias Analysis Implementation ------==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a CFL-based context-insensitive alias analysis -// algorithm. It does not depend on types. The algorithm is a mixture of the one -// described in "Demand-driven alias analysis for C" by Xin Zheng and Radu -// Rugina, and "Fast algorithms for Dyck-CFL-reachability with applications to -// Alias Analysis" by Zhang Q, Lyu M R, Yuan H, and Su Z. -- to summarize the -// papers, we build a graph of the uses of a variable, where each node is a -// memory location, and each edge is an action that happened on that memory -// location. The "actions" can be one of Dereference, Reference, or Assign. -// -// Two variables are considered as aliasing iff you can reach one value's node -// from the other value's node and the language formed by concatenating all of -// the edge labels (actions) conforms to a context-free grammar. -// -// Because this algorithm requires a graph search on each query, we execute the -// algorithm outlined in "Fast algorithms..." (mentioned above) -// in order to transform the graph into sets of variables that may alias in -// ~nlogn time (n = number of variables.), which makes queries take constant -// time. -//===----------------------------------------------------------------------===// - -#include "llvm/Analysis/CFLAliasAnalysis.h" -#include "StratifiedSets.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstVisitor.h" -#include "llvm/IR/Instructions.h" -#include "llvm/Pass.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <memory> -#include <tuple> - -using namespace llvm; - -#define DEBUG_TYPE "cfl-aa" - -CFLAAResult::CFLAAResult(const TargetLibraryInfo &TLI) : AAResultBase(TLI) {} -CFLAAResult::CFLAAResult(CFLAAResult &&Arg) : AAResultBase(std::move(Arg)) {} - -// \brief Information we have about a function and would like to keep around -struct CFLAAResult::FunctionInfo { - StratifiedSets<Value *> Sets; - // Lots of functions have < 4 returns. Adjust as necessary. - SmallVector<Value *, 4> ReturnedValues; - - FunctionInfo(StratifiedSets<Value *> &&S, SmallVector<Value *, 4> &&RV) - : Sets(std::move(S)), ReturnedValues(std::move(RV)) {} -}; - -// Try to go from a Value* to a Function*. Never returns nullptr. -static Optional<Function *> parentFunctionOfValue(Value *); - -// Returns possible functions called by the Inst* into the given -// SmallVectorImpl. Returns true if targets found, false otherwise. -// This is templated because InvokeInst/CallInst give us the same -// set of functions that we care about, and I don't like repeating -// myself. -template <typename Inst> -static bool getPossibleTargets(Inst *, SmallVectorImpl<Function *> &); - -// Some instructions need to have their users tracked. Instructions like -// `add` require you to get the users of the Instruction* itself, other -// instructions like `store` require you to get the users of the first -// operand. This function gets the "proper" value to track for each -// type of instruction we support. -static Optional<Value *> getTargetValue(Instruction *); - -// There are certain instructions (i.e. FenceInst, etc.) that we ignore. -// This notes that we should ignore those. -static bool hasUsefulEdges(Instruction *); - -const StratifiedIndex StratifiedLink::SetSentinel = - std::numeric_limits<StratifiedIndex>::max(); - -namespace { -// StratifiedInfo Attribute things. -typedef unsigned StratifiedAttr; -LLVM_CONSTEXPR unsigned MaxStratifiedAttrIndex = NumStratifiedAttrs; -LLVM_CONSTEXPR unsigned AttrAllIndex = 0; -LLVM_CONSTEXPR unsigned AttrGlobalIndex = 1; -LLVM_CONSTEXPR unsigned AttrUnknownIndex = 2; -LLVM_CONSTEXPR unsigned AttrFirstArgIndex = 3; -LLVM_CONSTEXPR unsigned AttrLastArgIndex = MaxStratifiedAttrIndex; -LLVM_CONSTEXPR unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex; - -LLVM_CONSTEXPR StratifiedAttr AttrNone = 0; -LLVM_CONSTEXPR StratifiedAttr AttrUnknown = 1 << AttrUnknownIndex; -LLVM_CONSTEXPR StratifiedAttr AttrAll = ~AttrNone; - -// \brief StratifiedSets call for knowledge of "direction", so this is how we -// represent that locally. -enum class Level { Same, Above, Below }; - -// \brief Edges can be one of four "weights" -- each weight must have an inverse -// weight (Assign has Assign; Reference has Dereference). -enum class EdgeType { - // The weight assigned when assigning from or to a value. For example, in: - // %b = getelementptr %a, 0 - // ...The relationships are %b assign %a, and %a assign %b. This used to be - // two edges, but having a distinction bought us nothing. - Assign, - - // The edge used when we have an edge going from some handle to a Value. - // Examples of this include: - // %b = load %a (%b Dereference %a) - // %b = extractelement %a, 0 (%a Dereference %b) - Dereference, - - // The edge used when our edge goes from a value to a handle that may have - // contained it at some point. Examples: - // %b = load %a (%a Reference %b) - // %b = extractelement %a, 0 (%b Reference %a) - Reference -}; - -// \brief Encodes the notion of a "use" -struct Edge { - // \brief Which value the edge is coming from - Value *From; - - // \brief Which value the edge is pointing to - Value *To; - - // \brief Edge weight - EdgeType Weight; - - // \brief Whether we aliased any external values along the way that may be - // invisible to the analysis (i.e. landingpad for exceptions, calls for - // interprocedural analysis, etc.) - StratifiedAttrs AdditionalAttrs; - - Edge(Value *From, Value *To, EdgeType W, StratifiedAttrs A) - : From(From), To(To), Weight(W), AdditionalAttrs(A) {} -}; - -// \brief Gets the edges our graph should have, based on an Instruction* -class GetEdgesVisitor : public InstVisitor<GetEdgesVisitor, void> { - CFLAAResult &AA; - SmallVectorImpl<Edge> &Output; - -public: - GetEdgesVisitor(CFLAAResult &AA, SmallVectorImpl<Edge> &Output) - : AA(AA), Output(Output) {} - - void visitInstruction(Instruction &) { - llvm_unreachable("Unsupported instruction encountered"); - } - - void visitPtrToIntInst(PtrToIntInst &Inst) { - auto *Ptr = Inst.getOperand(0); - Output.push_back(Edge(Ptr, Ptr, EdgeType::Assign, AttrUnknown)); - } - - void visitIntToPtrInst(IntToPtrInst &Inst) { - auto *Ptr = &Inst; - Output.push_back(Edge(Ptr, Ptr, EdgeType::Assign, AttrUnknown)); - } - - void visitCastInst(CastInst &Inst) { - Output.push_back( - Edge(&Inst, Inst.getOperand(0), EdgeType::Assign, AttrNone)); - } - - void visitBinaryOperator(BinaryOperator &Inst) { - auto *Op1 = Inst.getOperand(0); - auto *Op2 = Inst.getOperand(1); - Output.push_back(Edge(&Inst, Op1, EdgeType::Assign, AttrNone)); - Output.push_back(Edge(&Inst, Op2, EdgeType::Assign, AttrNone)); - } - - void visitAtomicCmpXchgInst(AtomicCmpXchgInst &Inst) { - auto *Ptr = Inst.getPointerOperand(); - auto *Val = Inst.getNewValOperand(); - Output.push_back(Edge(Ptr, Val, EdgeType::Dereference, AttrNone)); - } - - void visitAtomicRMWInst(AtomicRMWInst &Inst) { - auto *Ptr = Inst.getPointerOperand(); - auto *Val = Inst.getValOperand(); - Output.push_back(Edge(Ptr, Val, EdgeType::Dereference, AttrNone)); - } - - void visitPHINode(PHINode &Inst) { - for (Value *Val : Inst.incoming_values()) { - Output.push_back(Edge(&Inst, Val, EdgeType::Assign, AttrNone)); - } - } - - void visitGetElementPtrInst(GetElementPtrInst &Inst) { - auto *Op = Inst.getPointerOperand(); - Output.push_back(Edge(&Inst, Op, EdgeType::Assign, AttrNone)); - for (auto I = Inst.idx_begin(), E = Inst.idx_end(); I != E; ++I) - Output.push_back(Edge(&Inst, *I, EdgeType::Assign, AttrNone)); - } - - void visitSelectInst(SelectInst &Inst) { - // Condition is not processed here (The actual statement producing - // the condition result is processed elsewhere). For select, the - // condition is evaluated, but not loaded, stored, or assigned - // simply as a result of being the condition of a select. - - auto *TrueVal = Inst.getTrueValue(); - Output.push_back(Edge(&Inst, TrueVal, EdgeType::Assign, AttrNone)); - auto *FalseVal = Inst.getFalseValue(); - Output.push_back(Edge(&Inst, FalseVal, EdgeType::Assign, AttrNone)); - } - - void visitAllocaInst(AllocaInst &) {} - - void visitLoadInst(LoadInst &Inst) { - auto *Ptr = Inst.getPointerOperand(); - auto *Val = &Inst; - Output.push_back(Edge(Val, Ptr, EdgeType::Reference, AttrNone)); - } - - void visitStoreInst(StoreInst &Inst) { - auto *Ptr = Inst.getPointerOperand(); - auto *Val = Inst.getValueOperand(); - Output.push_back(Edge(Ptr, Val, EdgeType::Dereference, AttrNone)); - } - - void visitVAArgInst(VAArgInst &Inst) { - // We can't fully model va_arg here. For *Ptr = Inst.getOperand(0), it does - // two things: - // 1. Loads a value from *((T*)*Ptr). - // 2. Increments (stores to) *Ptr by some target-specific amount. - // For now, we'll handle this like a landingpad instruction (by placing the - // result in its own group, and having that group alias externals). - auto *Val = &Inst; - Output.push_back(Edge(Val, Val, EdgeType::Assign, AttrAll)); - } - - static bool isFunctionExternal(Function *Fn) { - return Fn->isDeclaration() || !Fn->hasLocalLinkage(); - } - - // Gets whether the sets at Index1 above, below, or equal to the sets at - // Index2. Returns None if they are not in the same set chain. - static Optional<Level> getIndexRelation(const StratifiedSets<Value *> &Sets, - StratifiedIndex Index1, - StratifiedIndex Index2) { - if (Index1 == Index2) - return Level::Same; - - const auto *Current = &Sets.getLink(Index1); - while (Current->hasBelow()) { - if (Current->Below == Index2) - return Level::Below; - Current = &Sets.getLink(Current->Below); - } - - Current = &Sets.getLink(Index1); - while (Current->hasAbove()) { - if (Current->Above == Index2) - return Level::Above; - Current = &Sets.getLink(Current->Above); - } - - return NoneType(); - } - - bool - tryInterproceduralAnalysis(const SmallVectorImpl<Function *> &Fns, - Value *FuncValue, - const iterator_range<User::op_iterator> &Args) { - const unsigned ExpectedMaxArgs = 8; - const unsigned MaxSupportedArgs = 50; - assert(Fns.size() > 0); - - // I put this here to give us an upper bound on time taken by IPA. Is it - // really (realistically) needed? Keep in mind that we do have an n^2 algo. - if (std::distance(Args.begin(), Args.end()) > (int)MaxSupportedArgs) - return false; - - // Exit early if we'll fail anyway - for (auto *Fn : Fns) { - if (isFunctionExternal(Fn) || Fn->isVarArg()) - return false; - auto &MaybeInfo = AA.ensureCached(Fn); - if (!MaybeInfo.hasValue()) - return false; - } - - SmallVector<Value *, ExpectedMaxArgs> Arguments(Args.begin(), Args.end()); - SmallVector<StratifiedInfo, ExpectedMaxArgs> Parameters; - for (auto *Fn : Fns) { - auto &Info = *AA.ensureCached(Fn); - auto &Sets = Info.Sets; - auto &RetVals = Info.ReturnedValues; - - Parameters.clear(); - for (auto &Param : Fn->args()) { - auto MaybeInfo = Sets.find(&Param); - // Did a new parameter somehow get added to the function/slip by? - if (!MaybeInfo.hasValue()) - return false; - Parameters.push_back(*MaybeInfo); - } - - // Adding an edge from argument -> return value for each parameter that - // may alias the return value - for (unsigned I = 0, E = Parameters.size(); I != E; ++I) { - auto &ParamInfo = Parameters[I]; - auto &ArgVal = Arguments[I]; - bool AddEdge = false; - StratifiedAttrs Externals; - for (unsigned X = 0, XE = RetVals.size(); X != XE; ++X) { - auto MaybeInfo = Sets.find(RetVals[X]); - if (!MaybeInfo.hasValue()) - return false; - - auto &RetInfo = *MaybeInfo; - auto RetAttrs = Sets.getLink(RetInfo.Index).Attrs; - auto ParamAttrs = Sets.getLink(ParamInfo.Index).Attrs; - auto MaybeRelation = - getIndexRelation(Sets, ParamInfo.Index, RetInfo.Index); - if (MaybeRelation.hasValue()) { - AddEdge = true; - Externals |= RetAttrs | ParamAttrs; - } - } - if (AddEdge) - Output.push_back(Edge(FuncValue, ArgVal, EdgeType::Assign, - StratifiedAttrs().flip())); - } - - if (Parameters.size() != Arguments.size()) - return false; - - // Adding edges between arguments for arguments that may end up aliasing - // each other. This is necessary for functions such as - // void foo(int** a, int** b) { *a = *b; } - // (Technically, the proper sets for this would be those below - // Arguments[I] and Arguments[X], but our algorithm will produce - // extremely similar, and equally correct, results either way) - for (unsigned I = 0, E = Arguments.size(); I != E; ++I) { - auto &MainVal = Arguments[I]; - auto &MainInfo = Parameters[I]; - auto &MainAttrs = Sets.getLink(MainInfo.Index).Attrs; - for (unsigned X = I + 1; X != E; ++X) { - auto &SubInfo = Parameters[X]; - auto &SubVal = Arguments[X]; - auto &SubAttrs = Sets.getLink(SubInfo.Index).Attrs; - auto MaybeRelation = - getIndexRelation(Sets, MainInfo.Index, SubInfo.Index); - - if (!MaybeRelation.hasValue()) - continue; - - auto NewAttrs = SubAttrs | MainAttrs; - Output.push_back(Edge(MainVal, SubVal, EdgeType::Assign, NewAttrs)); - } - } - } - return true; - } - - template <typename InstT> void visitCallLikeInst(InstT &Inst) { - // TODO: Add support for noalias args/all the other fun function attributes - // that we can tack on. - SmallVector<Function *, 4> Targets; - if (getPossibleTargets(&Inst, Targets)) { - if (tryInterproceduralAnalysis(Targets, &Inst, Inst.arg_operands())) - return; - // Cleanup from interprocedural analysis - Output.clear(); - } - - // Because the function is opaque, we need to note that anything - // could have happened to the arguments, and that the result could alias - // just about anything, too. - // The goal of the loop is in part to unify many Values into one set, so we - // don't care if the function is void there. - for (Value *V : Inst.arg_operands()) - Output.push_back(Edge(&Inst, V, EdgeType::Assign, AttrAll)); - if (Inst.getNumArgOperands() == 0 && - Inst.getType() != Type::getVoidTy(Inst.getContext())) - Output.push_back(Edge(&Inst, &Inst, EdgeType::Assign, AttrAll)); - } - - void visitCallInst(CallInst &Inst) { visitCallLikeInst(Inst); } - - void visitInvokeInst(InvokeInst &Inst) { visitCallLikeInst(Inst); } - - // Because vectors/aggregates are immutable and unaddressable, - // there's nothing we can do to coax a value out of them, other - // than calling Extract{Element,Value}. We can effectively treat - // them as pointers to arbitrary memory locations we can store in - // and load from. - void visitExtractElementInst(ExtractElementInst &Inst) { - auto *Ptr = Inst.getVectorOperand(); - auto *Val = &Inst; - Output.push_back(Edge(Val, Ptr, EdgeType::Reference, AttrNone)); - } - - void visitInsertElementInst(InsertElementInst &Inst) { - auto *Vec = Inst.getOperand(0); - auto *Val = Inst.getOperand(1); - Output.push_back(Edge(&Inst, Vec, EdgeType::Assign, AttrNone)); - Output.push_back(Edge(&Inst, Val, EdgeType::Dereference, AttrNone)); - } - - void visitLandingPadInst(LandingPadInst &Inst) { - // Exceptions come from "nowhere", from our analysis' perspective. - // So we place the instruction its own group, noting that said group may - // alias externals - Output.push_back(Edge(&Inst, &Inst, EdgeType::Assign, AttrAll)); - } - - void visitInsertValueInst(InsertValueInst &Inst) { - auto *Agg = Inst.getOperand(0); - auto *Val = Inst.getOperand(1); - Output.push_back(Edge(&Inst, Agg, EdgeType::Assign, AttrNone)); - Output.push_back(Edge(&Inst, Val, EdgeType::Dereference, AttrNone)); - } - - void visitExtractValueInst(ExtractValueInst &Inst) { - auto *Ptr = Inst.getAggregateOperand(); - Output.push_back(Edge(&Inst, Ptr, EdgeType::Reference, AttrNone)); - } - - void visitShuffleVectorInst(ShuffleVectorInst &Inst) { - auto *From1 = Inst.getOperand(0); - auto *From2 = Inst.getOperand(1); - Output.push_back(Edge(&Inst, From1, EdgeType::Assign, AttrNone)); - Output.push_back(Edge(&Inst, From2, EdgeType::Assign, AttrNone)); - } - - void visitConstantExpr(ConstantExpr *CE) { - switch (CE->getOpcode()) { - default: - llvm_unreachable("Unknown instruction type encountered!"); -// Build the switch statement using the Instruction.def file. -#define HANDLE_INST(NUM, OPCODE, CLASS) \ - case Instruction::OPCODE: \ - visit##OPCODE(*(CLASS *)CE); \ - break; -#include "llvm/IR/Instruction.def" - } - } -}; - -// For a given instruction, we need to know which Value* to get the -// users of in order to build our graph. In some cases (i.e. add), -// we simply need the Instruction*. In other cases (i.e. store), -// finding the users of the Instruction* is useless; we need to find -// the users of the first operand. This handles determining which -// value to follow for us. -// -// Note: we *need* to keep this in sync with GetEdgesVisitor. Add -// something to GetEdgesVisitor, add it here -- remove something from -// GetEdgesVisitor, remove it here. -class GetTargetValueVisitor - : public InstVisitor<GetTargetValueVisitor, Value *> { -public: - Value *visitInstruction(Instruction &Inst) { return &Inst; } - - Value *visitStoreInst(StoreInst &Inst) { return Inst.getPointerOperand(); } - - Value *visitAtomicCmpXchgInst(AtomicCmpXchgInst &Inst) { - return Inst.getPointerOperand(); - } - - Value *visitAtomicRMWInst(AtomicRMWInst &Inst) { - return Inst.getPointerOperand(); - } - - Value *visitInsertElementInst(InsertElementInst &Inst) { - return Inst.getOperand(0); - } - - Value *visitInsertValueInst(InsertValueInst &Inst) { - return Inst.getAggregateOperand(); - } -}; - -// Set building requires a weighted bidirectional graph. -template <typename EdgeTypeT> class WeightedBidirectionalGraph { -public: - typedef std::size_t Node; - -private: - const static Node StartNode = Node(0); - - struct Edge { - EdgeTypeT Weight; - Node Other; - - Edge(const EdgeTypeT &W, const Node &N) : Weight(W), Other(N) {} - - bool operator==(const Edge &E) const { - return Weight == E.Weight && Other == E.Other; - } - - bool operator!=(const Edge &E) const { return !operator==(E); } - }; - - struct NodeImpl { - std::vector<Edge> Edges; - }; - - std::vector<NodeImpl> NodeImpls; - - bool inbounds(Node NodeIndex) const { return NodeIndex < NodeImpls.size(); } - - const NodeImpl &getNode(Node N) const { return NodeImpls[N]; } - NodeImpl &getNode(Node N) { return NodeImpls[N]; } - -public: - // ----- Various Edge iterators for the graph ----- // - - // \brief Iterator for edges. Because this graph is bidirected, we don't - // allow modification of the edges using this iterator. Additionally, the - // iterator becomes invalid if you add edges to or from the node you're - // getting the edges of. - struct EdgeIterator : public std::iterator<std::forward_iterator_tag, - std::tuple<EdgeTypeT, Node *>> { - EdgeIterator(const typename std::vector<Edge>::const_iterator &Iter) - : Current(Iter) {} - - EdgeIterator(NodeImpl &Impl) : Current(Impl.begin()) {} - - EdgeIterator &operator++() { - ++Current; - return *this; - } - - EdgeIterator operator++(int) { - EdgeIterator Copy(Current); - operator++(); - return Copy; - } - - std::tuple<EdgeTypeT, Node> &operator*() { - Store = std::make_tuple(Current->Weight, Current->Other); - return Store; - } - - bool operator==(const EdgeIterator &Other) const { - return Current == Other.Current; - } - - bool operator!=(const EdgeIterator &Other) const { - return !operator==(Other); - } - - private: - typename std::vector<Edge>::const_iterator Current; - std::tuple<EdgeTypeT, Node> Store; - }; - - // Wrapper for EdgeIterator with begin()/end() calls. - struct EdgeIterable { - EdgeIterable(const std::vector<Edge> &Edges) - : BeginIter(Edges.begin()), EndIter(Edges.end()) {} - - EdgeIterator begin() { return EdgeIterator(BeginIter); } - - EdgeIterator end() { return EdgeIterator(EndIter); } - - private: - typename std::vector<Edge>::const_iterator BeginIter; - typename std::vector<Edge>::const_iterator EndIter; - }; - - // ----- Actual graph-related things ----- // - - WeightedBidirectionalGraph() {} - - WeightedBidirectionalGraph(WeightedBidirectionalGraph<EdgeTypeT> &&Other) - : NodeImpls(std::move(Other.NodeImpls)) {} - - WeightedBidirectionalGraph<EdgeTypeT> & - operator=(WeightedBidirectionalGraph<EdgeTypeT> &&Other) { - NodeImpls = std::move(Other.NodeImpls); - return *this; - } - - Node addNode() { - auto Index = NodeImpls.size(); - auto NewNode = Node(Index); - NodeImpls.push_back(NodeImpl()); - return NewNode; - } - - void addEdge(Node From, Node To, const EdgeTypeT &Weight, - const EdgeTypeT &ReverseWeight) { - assert(inbounds(From)); - assert(inbounds(To)); - auto &FromNode = getNode(From); - auto &ToNode = getNode(To); - FromNode.Edges.push_back(Edge(Weight, To)); - ToNode.Edges.push_back(Edge(ReverseWeight, From)); - } - - EdgeIterable edgesFor(const Node &N) const { - const auto &Node = getNode(N); - return EdgeIterable(Node.Edges); - } - - bool empty() const { return NodeImpls.empty(); } - std::size_t size() const { return NodeImpls.size(); } - - // \brief Gets an arbitrary node in the graph as a starting point for - // traversal. - Node getEntryNode() { - assert(inbounds(StartNode)); - return StartNode; - } -}; - -typedef WeightedBidirectionalGraph<std::pair<EdgeType, StratifiedAttrs>> GraphT; -typedef DenseMap<Value *, GraphT::Node> NodeMapT; -} - -//===----------------------------------------------------------------------===// -// Function declarations that require types defined in the namespace above -//===----------------------------------------------------------------------===// - -// Given an argument number, returns the appropriate Attr index to set. -static StratifiedAttr argNumberToAttrIndex(StratifiedAttr); - -// Given a Value, potentially return which AttrIndex it maps to. -static Optional<StratifiedAttr> valueToAttrIndex(Value *Val); - -// Gets the inverse of a given EdgeType. -static EdgeType flipWeight(EdgeType); - -// Gets edges of the given Instruction*, writing them to the SmallVector*. -static void argsToEdges(CFLAAResult &, Instruction *, SmallVectorImpl<Edge> &); - -// Gets edges of the given ConstantExpr*, writing them to the SmallVector*. -static void argsToEdges(CFLAAResult &, ConstantExpr *, SmallVectorImpl<Edge> &); - -// Gets the "Level" that one should travel in StratifiedSets -// given an EdgeType. -static Level directionOfEdgeType(EdgeType); - -// Builds the graph needed for constructing the StratifiedSets for the -// given function -static void buildGraphFrom(CFLAAResult &, Function *, - SmallVectorImpl<Value *> &, NodeMapT &, GraphT &); - -// Gets the edges of a ConstantExpr as if it was an Instruction. This -// function also acts on any nested ConstantExprs, adding the edges -// of those to the given SmallVector as well. -static void constexprToEdges(CFLAAResult &, ConstantExpr &, - SmallVectorImpl<Edge> &); - -// Given an Instruction, this will add it to the graph, along with any -// Instructions that are potentially only available from said Instruction -// For example, given the following line: -// %0 = load i16* getelementptr ([1 x i16]* @a, 0, 0), align 2 -// addInstructionToGraph would add both the `load` and `getelementptr` -// instructions to the graph appropriately. -static void addInstructionToGraph(CFLAAResult &, Instruction &, - SmallVectorImpl<Value *> &, NodeMapT &, - GraphT &); - -// Notes whether it would be pointless to add the given Value to our sets. -static bool canSkipAddingToSets(Value *Val); - -static Optional<Function *> parentFunctionOfValue(Value *Val) { - if (auto *Inst = dyn_cast<Instruction>(Val)) { - auto *Bb = Inst->getParent(); - return Bb->getParent(); - } - - if (auto *Arg = dyn_cast<Argument>(Val)) - return Arg->getParent(); - return NoneType(); -} - -template <typename Inst> -static bool getPossibleTargets(Inst *Call, - SmallVectorImpl<Function *> &Output) { - if (auto *Fn = Call->getCalledFunction()) { - Output.push_back(Fn); - return true; - } - - // TODO: If the call is indirect, we might be able to enumerate all potential - // targets of the call and return them, rather than just failing. - return false; -} - -static Optional<Value *> getTargetValue(Instruction *Inst) { - GetTargetValueVisitor V; - return V.visit(Inst); -} - -static bool hasUsefulEdges(Instruction *Inst) { - bool IsNonInvokeTerminator = - isa<TerminatorInst>(Inst) && !isa<InvokeInst>(Inst); - return !isa<CmpInst>(Inst) && !isa<FenceInst>(Inst) && !IsNonInvokeTerminator; -} - -static bool hasUsefulEdges(ConstantExpr *CE) { - // ConstantExpr doesn't have terminators, invokes, or fences, so only needs - // to check for compares. - return CE->getOpcode() != Instruction::ICmp && - CE->getOpcode() != Instruction::FCmp; -} - -static Optional<StratifiedAttr> valueToAttrIndex(Value *Val) { - if (isa<GlobalValue>(Val)) - return AttrGlobalIndex; - - if (auto *Arg = dyn_cast<Argument>(Val)) - // Only pointer arguments should have the argument attribute, - // because things can't escape through scalars without us seeing a - // cast, and thus, interaction with them doesn't matter. - if (!Arg->hasNoAliasAttr() && Arg->getType()->isPointerTy()) - return argNumberToAttrIndex(Arg->getArgNo()); - return NoneType(); -} - -static StratifiedAttr argNumberToAttrIndex(unsigned ArgNum) { - if (ArgNum >= AttrMaxNumArgs) - return AttrAllIndex; - return ArgNum + AttrFirstArgIndex; -} - -static EdgeType flipWeight(EdgeType Initial) { - switch (Initial) { - case EdgeType::Assign: - return EdgeType::Assign; - case EdgeType::Dereference: - return EdgeType::Reference; - case EdgeType::Reference: - return EdgeType::Dereference; - } - llvm_unreachable("Incomplete coverage of EdgeType enum"); -} - -static void argsToEdges(CFLAAResult &Analysis, Instruction *Inst, - SmallVectorImpl<Edge> &Output) { - assert(hasUsefulEdges(Inst) && - "Expected instructions to have 'useful' edges"); - GetEdgesVisitor v(Analysis, Output); - v.visit(Inst); -} - -static void argsToEdges(CFLAAResult &Analysis, ConstantExpr *CE, - SmallVectorImpl<Edge> &Output) { - assert(hasUsefulEdges(CE) && "Expected constant expr to have 'useful' edges"); - GetEdgesVisitor v(Analysis, Output); - v.visitConstantExpr(CE); -} - -static Level directionOfEdgeType(EdgeType Weight) { - switch (Weight) { - case EdgeType::Reference: - return Level::Above; - case EdgeType::Dereference: - return Level::Below; - case EdgeType::Assign: - return Level::Same; - } - llvm_unreachable("Incomplete switch coverage"); -} - -static void constexprToEdges(CFLAAResult &Analysis, - ConstantExpr &CExprToCollapse, - SmallVectorImpl<Edge> &Results) { - SmallVector<ConstantExpr *, 4> Worklist; - Worklist.push_back(&CExprToCollapse); - - SmallVector<Edge, 8> ConstexprEdges; - SmallPtrSet<ConstantExpr *, 4> Visited; - while (!Worklist.empty()) { - auto *CExpr = Worklist.pop_back_val(); - - if (!hasUsefulEdges(CExpr)) - continue; - - ConstexprEdges.clear(); - argsToEdges(Analysis, CExpr, ConstexprEdges); - for (auto &Edge : ConstexprEdges) { - if (auto *Nested = dyn_cast<ConstantExpr>(Edge.From)) - if (Visited.insert(Nested).second) - Worklist.push_back(Nested); - - if (auto *Nested = dyn_cast<ConstantExpr>(Edge.To)) - if (Visited.insert(Nested).second) - Worklist.push_back(Nested); - } - - Results.append(ConstexprEdges.begin(), ConstexprEdges.end()); - } -} - -static void addInstructionToGraph(CFLAAResult &Analysis, Instruction &Inst, - SmallVectorImpl<Value *> &ReturnedValues, - NodeMapT &Map, GraphT &Graph) { - const auto findOrInsertNode = [&Map, &Graph](Value *Val) { - auto Pair = Map.insert(std::make_pair(Val, GraphT::Node())); - auto &Iter = Pair.first; - if (Pair.second) { - auto NewNode = Graph.addNode(); - Iter->second = NewNode; - } - return Iter->second; - }; - - // We don't want the edges of most "return" instructions, but we *do* want - // to know what can be returned. - if (isa<ReturnInst>(&Inst)) - ReturnedValues.push_back(&Inst); - - if (!hasUsefulEdges(&Inst)) - return; - - SmallVector<Edge, 8> Edges; - argsToEdges(Analysis, &Inst, Edges); - - // In the case of an unused alloca (or similar), edges may be empty. Note - // that it exists so we can potentially answer NoAlias. - if (Edges.empty()) { - auto MaybeVal = getTargetValue(&Inst); - assert(MaybeVal.hasValue()); - auto *Target = *MaybeVal; - findOrInsertNode(Target); - return; - } - - const auto addEdgeToGraph = [&Graph, &findOrInsertNode](const Edge &E) { - auto To = findOrInsertNode(E.To); - auto From = findOrInsertNode(E.From); - auto FlippedWeight = flipWeight(E.Weight); - auto Attrs = E.AdditionalAttrs; - Graph.addEdge(From, To, std::make_pair(E.Weight, Attrs), - std::make_pair(FlippedWeight, Attrs)); - }; - - SmallVector<ConstantExpr *, 4> ConstantExprs; - for (const Edge &E : Edges) { - addEdgeToGraph(E); - if (auto *Constexpr = dyn_cast<ConstantExpr>(E.To)) - ConstantExprs.push_back(Constexpr); - if (auto *Constexpr = dyn_cast<ConstantExpr>(E.From)) - ConstantExprs.push_back(Constexpr); - } - - for (ConstantExpr *CE : ConstantExprs) { - Edges.clear(); - constexprToEdges(Analysis, *CE, Edges); - std::for_each(Edges.begin(), Edges.end(), addEdgeToGraph); - } -} - -// Aside: We may remove graph construction entirely, because it doesn't really -// buy us much that we don't already have. I'd like to add interprocedural -// analysis prior to this however, in case that somehow requires the graph -// produced by this for efficient execution -static void buildGraphFrom(CFLAAResult &Analysis, Function *Fn, - SmallVectorImpl<Value *> &ReturnedValues, - NodeMapT &Map, GraphT &Graph) { - for (auto &Bb : Fn->getBasicBlockList()) - for (auto &Inst : Bb.getInstList()) - addInstructionToGraph(Analysis, Inst, ReturnedValues, Map, Graph); -} - -static bool canSkipAddingToSets(Value *Val) { - // Constants can share instances, which may falsely unify multiple - // sets, e.g. in - // store i32* null, i32** %ptr1 - // store i32* null, i32** %ptr2 - // clearly ptr1 and ptr2 should not be unified into the same set, so - // we should filter out the (potentially shared) instance to - // i32* null. - if (isa<Constant>(Val)) { - bool Container = isa<ConstantVector>(Val) || isa<ConstantArray>(Val) || - isa<ConstantStruct>(Val); - // TODO: Because all of these things are constant, we can determine whether - // the data is *actually* mutable at graph building time. This will probably - // come for free/cheap with offset awareness. - bool CanStoreMutableData = - isa<GlobalValue>(Val) || isa<ConstantExpr>(Val) || Container; - return !CanStoreMutableData; - } - - return false; -} - -// Builds the graph + StratifiedSets for a function. -CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) { - NodeMapT Map; - GraphT Graph; - SmallVector<Value *, 4> ReturnedValues; - - buildGraphFrom(*this, Fn, ReturnedValues, Map, Graph); - - DenseMap<GraphT::Node, Value *> NodeValueMap; - NodeValueMap.resize(Map.size()); - for (const auto &Pair : Map) - NodeValueMap.insert(std::make_pair(Pair.second, Pair.first)); - - const auto findValueOrDie = [&NodeValueMap](GraphT::Node Node) { - auto ValIter = NodeValueMap.find(Node); - assert(ValIter != NodeValueMap.end()); - return ValIter->second; - }; - - StratifiedSetsBuilder<Value *> Builder; - - SmallVector<GraphT::Node, 16> Worklist; - for (auto &Pair : Map) { - Worklist.clear(); - - auto *Value = Pair.first; - Builder.add(Value); - auto InitialNode = Pair.second; - Worklist.push_back(InitialNode); - while (!Worklist.empty()) { - auto Node = Worklist.pop_back_val(); - auto *CurValue = findValueOrDie(Node); - if (canSkipAddingToSets(CurValue)) - continue; - - for (const auto &EdgeTuple : Graph.edgesFor(Node)) { - auto Weight = std::get<0>(EdgeTuple); - auto Label = Weight.first; - auto &OtherNode = std::get<1>(EdgeTuple); - auto *OtherValue = findValueOrDie(OtherNode); - - if (canSkipAddingToSets(OtherValue)) - continue; - - bool Added; - switch (directionOfEdgeType(Label)) { - case Level::Above: - Added = Builder.addAbove(CurValue, OtherValue); - break; - case Level::Below: - Added = Builder.addBelow(CurValue, OtherValue); - break; - case Level::Same: - Added = Builder.addWith(CurValue, OtherValue); - break; - } - - auto Aliasing = Weight.second; - if (auto MaybeCurIndex = valueToAttrIndex(CurValue)) - Aliasing.set(*MaybeCurIndex); - if (auto MaybeOtherIndex = valueToAttrIndex(OtherValue)) - Aliasing.set(*MaybeOtherIndex); - Builder.noteAttributes(CurValue, Aliasing); - Builder.noteAttributes(OtherValue, Aliasing); - - if (Added) - Worklist.push_back(OtherNode); - } - } - } - - // There are times when we end up with parameters not in our graph (i.e. if - // it's only used as the condition of a branch). Other bits of code depend on - // things that were present during construction being present in the graph. - // So, we add all present arguments here. - for (auto &Arg : Fn->args()) { - if (!Builder.add(&Arg)) - continue; - - auto Attrs = valueToAttrIndex(&Arg); - if (Attrs.hasValue()) - Builder.noteAttributes(&Arg, *Attrs); - } - - return FunctionInfo(Builder.build(), std::move(ReturnedValues)); -} - -void CFLAAResult::scan(Function *Fn) { - auto InsertPair = Cache.insert(std::make_pair(Fn, Optional<FunctionInfo>())); - (void)InsertPair; - assert(InsertPair.second && - "Trying to scan a function that has already been cached"); - - FunctionInfo Info(buildSetsFrom(Fn)); - Cache[Fn] = std::move(Info); - Handles.push_front(FunctionHandle(Fn, this)); -} - -void CFLAAResult::evict(Function *Fn) { Cache.erase(Fn); } - -/// \brief Ensures that the given function is available in the cache. -/// Returns the appropriate entry from the cache. -const Optional<CFLAAResult::FunctionInfo> & -CFLAAResult::ensureCached(Function *Fn) { - auto Iter = Cache.find(Fn); - if (Iter == Cache.end()) { - scan(Fn); - Iter = Cache.find(Fn); - assert(Iter != Cache.end()); - assert(Iter->second.hasValue()); - } - return Iter->second; -} - -AliasResult CFLAAResult::query(const MemoryLocation &LocA, - const MemoryLocation &LocB) { - auto *ValA = const_cast<Value *>(LocA.Ptr); - auto *ValB = const_cast<Value *>(LocB.Ptr); - - Function *Fn = nullptr; - auto MaybeFnA = parentFunctionOfValue(ValA); - auto MaybeFnB = parentFunctionOfValue(ValB); - if (!MaybeFnA.hasValue() && !MaybeFnB.hasValue()) { - // The only times this is known to happen are when globals + InlineAsm - // are involved - DEBUG(dbgs() << "CFLAA: could not extract parent function information.\n"); - return MayAlias; - } - - if (MaybeFnA.hasValue()) { - Fn = *MaybeFnA; - assert((!MaybeFnB.hasValue() || *MaybeFnB == *MaybeFnA) && - "Interprocedural queries not supported"); - } else { - Fn = *MaybeFnB; - } - - assert(Fn != nullptr); - auto &MaybeInfo = ensureCached(Fn); - assert(MaybeInfo.hasValue()); - - auto &Sets = MaybeInfo->Sets; - auto MaybeA = Sets.find(ValA); - if (!MaybeA.hasValue()) - return MayAlias; - - auto MaybeB = Sets.find(ValB); - if (!MaybeB.hasValue()) - return MayAlias; - - auto SetA = *MaybeA; - auto SetB = *MaybeB; - auto AttrsA = Sets.getLink(SetA.Index).Attrs; - auto AttrsB = Sets.getLink(SetB.Index).Attrs; - - // Stratified set attributes are used as markets to signify whether a member - // of a StratifiedSet (or a member of a set above the current set) has - // interacted with either arguments or globals. "Interacted with" meaning - // its value may be different depending on the value of an argument or - // global. The thought behind this is that, because arguments and globals - // may alias each other, if AttrsA and AttrsB have touched args/globals, - // we must conservatively say that they alias. However, if at least one of - // the sets has no values that could legally be altered by changing the value - // of an argument or global, then we don't have to be as conservative. - if (AttrsA.any() && AttrsB.any()) - return MayAlias; - - // We currently unify things even if the accesses to them may not be in - // bounds, so we can't return partial alias here because we don't - // know whether the pointer is really within the object or not. - // IE Given an out of bounds GEP and an alloca'd pointer, we may - // unify the two. We can't return partial alias for this case. - // Since we do not currently track enough information to - // differentiate - - if (SetA.Index == SetB.Index) - return MayAlias; - - return NoAlias; -} - -CFLAAResult CFLAA::run(Function &F, AnalysisManager<Function> *AM) { - return CFLAAResult(AM->getResult<TargetLibraryAnalysis>(F)); -} - -char CFLAA::PassID; - -char CFLAAWrapperPass::ID = 0; -INITIALIZE_PASS_BEGIN(CFLAAWrapperPass, "cfl-aa", "CFL-Based Alias Analysis", - false, true) -INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) -INITIALIZE_PASS_END(CFLAAWrapperPass, "cfl-aa", "CFL-Based Alias Analysis", - false, true) - -ImmutablePass *llvm::createCFLAAWrapperPass() { return new CFLAAWrapperPass(); } - -CFLAAWrapperPass::CFLAAWrapperPass() : ImmutablePass(ID) { - initializeCFLAAWrapperPassPass(*PassRegistry::getPassRegistry()); -} - -bool CFLAAWrapperPass::doInitialization(Module &M) { - Result.reset( - new CFLAAResult(getAnalysis<TargetLibraryInfoWrapperPass>().getTLI())); - return false; -} - -bool CFLAAWrapperPass::doFinalization(Module &M) { - Result.reset(); - return false; -} - -void CFLAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<TargetLibraryInfoWrapperPass>(); -} diff --git a/gnu/llvm/lib/Analysis/Makefile b/gnu/llvm/lib/Analysis/Makefile deleted file mode 100644 index 93fd7f9bdd9..00000000000 --- a/gnu/llvm/lib/Analysis/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Analysis/Makefile -------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMAnalysis -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/AsmParser/Makefile b/gnu/llvm/lib/AsmParser/Makefile deleted file mode 100644 index 995bb0e130e..00000000000 --- a/gnu/llvm/lib/AsmParser/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/AsmParser/Makefile ------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME := LLVMAsmParser -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/AsmParser/module.modulemap b/gnu/llvm/lib/AsmParser/module.modulemap deleted file mode 100644 index cc300060b3f..00000000000 --- a/gnu/llvm/lib/AsmParser/module.modulemap +++ /dev/null @@ -1 +0,0 @@ -module AsmParser { requires cplusplus umbrella "." module * { export * } } diff --git a/gnu/llvm/lib/Bitcode/Makefile b/gnu/llvm/lib/Bitcode/Makefile deleted file mode 100644 index 2d6b5ad1fe8..00000000000 --- a/gnu/llvm/lib/Bitcode/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/Bitcode/Makefile --------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -PARALLEL_DIRS = Reader Writer - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Bitcode/Reader/Makefile b/gnu/llvm/lib/Bitcode/Reader/Makefile deleted file mode 100644 index 59af8d53a73..00000000000 --- a/gnu/llvm/lib/Bitcode/Reader/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Bitcode/Reader/Makefile -------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMBitReader -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Bitcode/Writer/Makefile b/gnu/llvm/lib/Bitcode/Writer/Makefile deleted file mode 100644 index 7b0bd72159a..00000000000 --- a/gnu/llvm/lib/Bitcode/Writer/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Bitcode/Reader/Makefile -------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMBitWriter -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Bitcode/module.modulemap b/gnu/llvm/lib/Bitcode/module.modulemap deleted file mode 100644 index 7df1a0a3c72..00000000000 --- a/gnu/llvm/lib/Bitcode/module.modulemap +++ /dev/null @@ -1 +0,0 @@ -module Bitcode { requires cplusplus umbrella "." module * { export * } } diff --git a/gnu/llvm/lib/CodeGen/AsmPrinter/Makefile b/gnu/llvm/lib/CodeGen/AsmPrinter/Makefile deleted file mode 100644 index 60aa6cbcf6f..00000000000 --- a/gnu/llvm/lib/CodeGen/AsmPrinter/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/CodeGen/AsmPrinter/Makefile ---------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMAsmPrinter - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp b/gnu/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp deleted file mode 100644 index 1e2f55b7115..00000000000 --- a/gnu/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp +++ /dev/null @@ -1,411 +0,0 @@ -//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp --*- C++ -*--===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains support for writing line tables info into COFF files. -// -//===----------------------------------------------------------------------===// - -#include "WinCodeViewLineTables.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/COFF.h" - -namespace llvm { - -StringRef WinCodeViewLineTables::getFullFilepath(const MDNode *S) { - assert(S); - assert((isa<DICompileUnit>(S) || isa<DIFile>(S) || isa<DISubprogram>(S) || - isa<DILexicalBlockBase>(S)) && - "Unexpected scope info"); - - auto *Scope = cast<DIScope>(S); - StringRef Dir = Scope->getDirectory(), - Filename = Scope->getFilename(); - std::string &Filepath = - DirAndFilenameToFilepathMap[std::make_pair(Dir, Filename)]; - if (!Filepath.empty()) - return Filepath; - - // Clang emits directory and relative filename info into the IR, but CodeView - // operates on full paths. We could change Clang to emit full paths too, but - // that would increase the IR size and probably not needed for other users. - // For now, just concatenate and canonicalize the path here. - if (Filename.find(':') == 1) - Filepath = Filename; - else - Filepath = (Dir + "\\" + Filename).str(); - - // Canonicalize the path. We have to do it textually because we may no longer - // have access the file in the filesystem. - // First, replace all slashes with backslashes. - std::replace(Filepath.begin(), Filepath.end(), '/', '\\'); - - // Remove all "\.\" with "\". - size_t Cursor = 0; - while ((Cursor = Filepath.find("\\.\\", Cursor)) != std::string::npos) - Filepath.erase(Cursor, 2); - - // Replace all "\XXX\..\" with "\". Don't try too hard though as the original - // path should be well-formatted, e.g. start with a drive letter, etc. - Cursor = 0; - while ((Cursor = Filepath.find("\\..\\", Cursor)) != std::string::npos) { - // Something's wrong if the path starts with "\..\", abort. - if (Cursor == 0) - break; - - size_t PrevSlash = Filepath.rfind('\\', Cursor - 1); - if (PrevSlash == std::string::npos) - // Something's wrong, abort. - break; - - Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash); - // The next ".." might be following the one we've just erased. - Cursor = PrevSlash; - } - - // Remove all duplicate backslashes. - Cursor = 0; - while ((Cursor = Filepath.find("\\\\", Cursor)) != std::string::npos) - Filepath.erase(Cursor, 1); - - return Filepath; -} - -void WinCodeViewLineTables::maybeRecordLocation(DebugLoc DL, - const MachineFunction *MF) { - const MDNode *Scope = DL.getScope(); - if (!Scope) - return; - unsigned LineNumber = DL.getLine(); - // Skip this line if it is longer than the maximum we can record. - if (LineNumber > COFF::CVL_MaxLineNumber) - return; - - unsigned ColumnNumber = DL.getCol(); - // Truncate the column number if it is longer than the maximum we can record. - if (ColumnNumber > COFF::CVL_MaxColumnNumber) - ColumnNumber = 0; - - StringRef Filename = getFullFilepath(Scope); - - // Skip this instruction if it has the same file:line as the previous one. - assert(CurFn); - if (!CurFn->Instrs.empty()) { - const InstrInfoTy &LastInstr = InstrInfo[CurFn->Instrs.back()]; - if (LastInstr.Filename == Filename && LastInstr.LineNumber == LineNumber && - LastInstr.ColumnNumber == ColumnNumber) - return; - } - FileNameRegistry.add(Filename); - - MCSymbol *MCL = Asm->MMI->getContext().createTempSymbol(); - Asm->OutStreamer->EmitLabel(MCL); - CurFn->Instrs.push_back(MCL); - InstrInfo[MCL] = InstrInfoTy(Filename, LineNumber, ColumnNumber); -} - -WinCodeViewLineTables::WinCodeViewLineTables(AsmPrinter *AP) - : Asm(nullptr), CurFn(nullptr) { - MachineModuleInfo *MMI = AP->MMI; - - // If module doesn't have named metadata anchors or COFF debug section - // is not available, skip any debug info related stuff. - if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") || - !AP->getObjFileLowering().getCOFFDebugSymbolsSection()) - return; - - // Tell MMI that we have debug info. - MMI->setDebugInfoAvailability(true); - Asm = AP; -} - -void WinCodeViewLineTables::endModule() { - if (FnDebugInfo.empty()) - return; - - assert(Asm != nullptr); - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getCOFFDebugSymbolsSection()); - Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC); - - // The COFF .debug$S section consists of several subsections, each starting - // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length - // of the payload followed by the payload itself. The subsections are 4-byte - // aligned. - - // Emit per-function debug information. This code is extracted into a - // separate function for readability. - for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I) - emitDebugInfoForFunction(VisitedFunctions[I]); - - // This subsection holds a file index to offset in string table table. - Asm->OutStreamer->AddComment("File index to string table offset subsection"); - Asm->EmitInt32(COFF::DEBUG_INDEX_SUBSECTION); - size_t NumFilenames = FileNameRegistry.Infos.size(); - Asm->EmitInt32(8 * NumFilenames); - for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) { - StringRef Filename = FileNameRegistry.Filenames[I]; - // For each unique filename, just write its offset in the string table. - Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset); - // The function name offset is not followed by any additional data. - Asm->EmitInt32(0); - } - - // This subsection holds the string table. - Asm->OutStreamer->AddComment("String table"); - Asm->EmitInt32(COFF::DEBUG_STRING_TABLE_SUBSECTION); - Asm->EmitInt32(FileNameRegistry.LastOffset); - // The payload starts with a null character. - Asm->EmitInt8(0); - - for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) { - // Just emit unique filenames one by one, separated by a null character. - Asm->OutStreamer->EmitBytes(FileNameRegistry.Filenames[I]); - Asm->EmitInt8(0); - } - - // No more subsections. Fill with zeros to align the end of the section by 4. - Asm->OutStreamer->EmitFill((-FileNameRegistry.LastOffset) % 4, 0); - - clear(); -} - -static void EmitLabelDiff(MCStreamer &Streamer, - const MCSymbol *From, const MCSymbol *To, - unsigned int Size = 4) { - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - MCContext &Context = Streamer.getContext(); - const MCExpr *FromRef = MCSymbolRefExpr::create(From, Variant, Context), - *ToRef = MCSymbolRefExpr::create(To, Variant, Context); - const MCExpr *AddrDelta = - MCBinaryExpr::create(MCBinaryExpr::Sub, ToRef, FromRef, Context); - Streamer.EmitValue(AddrDelta, Size); -} - -void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { - // For each function there is a separate subsection - // which holds the PC to file:line table. - const MCSymbol *Fn = Asm->getSymbol(GV); - assert(Fn); - - const FunctionInfo &FI = FnDebugInfo[GV]; - if (FI.Instrs.empty()) - return; - assert(FI.End && "Don't know where the function ends?"); - - StringRef GVName = GV->getName(); - StringRef FuncName; - if (auto *SP = getDISubprogram(GV)) - FuncName = SP->getDisplayName(); - - // FIXME Clang currently sets DisplayName to "bar" for a C++ - // "namespace_foo::bar" function, see PR21528. Luckily, dbghelp.dll is trying - // to demangle display names anyways, so let's just put a mangled name into - // the symbols subsection until Clang gives us what we need. - if (GVName.startswith("\01?")) - FuncName = GVName.substr(1); - // Emit a symbol subsection, required by VS2012+ to find function boundaries. - MCSymbol *SymbolsBegin = Asm->MMI->getContext().createTempSymbol(), - *SymbolsEnd = Asm->MMI->getContext().createTempSymbol(); - Asm->OutStreamer->AddComment("Symbol subsection for " + Twine(FuncName)); - Asm->EmitInt32(COFF::DEBUG_SYMBOL_SUBSECTION); - EmitLabelDiff(*Asm->OutStreamer, SymbolsBegin, SymbolsEnd); - Asm->OutStreamer->EmitLabel(SymbolsBegin); - { - MCSymbol *ProcSegmentBegin = Asm->MMI->getContext().createTempSymbol(), - *ProcSegmentEnd = Asm->MMI->getContext().createTempSymbol(); - EmitLabelDiff(*Asm->OutStreamer, ProcSegmentBegin, ProcSegmentEnd, 2); - Asm->OutStreamer->EmitLabel(ProcSegmentBegin); - - Asm->EmitInt16(COFF::DEBUG_SYMBOL_TYPE_PROC_START); - // Some bytes of this segment don't seem to be required for basic debugging, - // so just fill them with zeroes. - Asm->OutStreamer->EmitFill(12, 0); - // This is the important bit that tells the debugger where the function - // code is located and what's its size: - EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End); - Asm->OutStreamer->EmitFill(12, 0); - Asm->OutStreamer->EmitCOFFSecRel32(Fn); - Asm->OutStreamer->EmitCOFFSectionIndex(Fn); - Asm->EmitInt8(0); - // Emit the function display name as a null-terminated string. - Asm->OutStreamer->EmitBytes(FuncName); - Asm->EmitInt8(0); - Asm->OutStreamer->EmitLabel(ProcSegmentEnd); - - // We're done with this function. - Asm->EmitInt16(0x0002); - Asm->EmitInt16(COFF::DEBUG_SYMBOL_TYPE_PROC_END); - } - Asm->OutStreamer->EmitLabel(SymbolsEnd); - // Every subsection must be aligned to a 4-byte boundary. - Asm->OutStreamer->EmitFill((-FuncName.size()) % 4, 0); - - // PCs/Instructions are grouped into segments sharing the same filename. - // Pre-calculate the lengths (in instructions) of these segments and store - // them in a map for convenience. Each index in the map is the sequential - // number of the respective instruction that starts a new segment. - DenseMap<size_t, size_t> FilenameSegmentLengths; - size_t LastSegmentEnd = 0; - StringRef PrevFilename = InstrInfo[FI.Instrs[0]].Filename; - for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) { - if (PrevFilename == InstrInfo[FI.Instrs[J]].Filename) - continue; - FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd; - LastSegmentEnd = J; - PrevFilename = InstrInfo[FI.Instrs[J]].Filename; - } - FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd; - - // Emit a line table subsection, required to do PC-to-file:line lookup. - Asm->OutStreamer->AddComment("Line table subsection for " + Twine(FuncName)); - Asm->EmitInt32(COFF::DEBUG_LINE_TABLE_SUBSECTION); - MCSymbol *LineTableBegin = Asm->MMI->getContext().createTempSymbol(), - *LineTableEnd = Asm->MMI->getContext().createTempSymbol(); - EmitLabelDiff(*Asm->OutStreamer, LineTableBegin, LineTableEnd); - Asm->OutStreamer->EmitLabel(LineTableBegin); - - // Identify the function this subsection is for. - Asm->OutStreamer->EmitCOFFSecRel32(Fn); - Asm->OutStreamer->EmitCOFFSectionIndex(Fn); - // Insert flags after a 16-bit section index. - Asm->EmitInt16(COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS); - - // Length of the function's code, in bytes. - EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End); - - // PC-to-linenumber lookup table: - MCSymbol *FileSegmentEnd = nullptr; - - // The start of the last segment: - size_t LastSegmentStart = 0; - - auto FinishPreviousChunk = [&] { - if (!FileSegmentEnd) - return; - for (size_t ColSegI = LastSegmentStart, - ColSegEnd = ColSegI + FilenameSegmentLengths[LastSegmentStart]; - ColSegI != ColSegEnd; ++ColSegI) { - unsigned ColumnNumber = InstrInfo[FI.Instrs[ColSegI]].ColumnNumber; - assert(ColumnNumber <= COFF::CVL_MaxColumnNumber); - Asm->EmitInt16(ColumnNumber); // Start column - Asm->EmitInt16(0); // End column - } - Asm->OutStreamer->EmitLabel(FileSegmentEnd); - }; - - for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) { - MCSymbol *Instr = FI.Instrs[J]; - assert(InstrInfo.count(Instr)); - - if (FilenameSegmentLengths.count(J)) { - // We came to a beginning of a new filename segment. - FinishPreviousChunk(); - StringRef CurFilename = InstrInfo[FI.Instrs[J]].Filename; - assert(FileNameRegistry.Infos.count(CurFilename)); - size_t IndexInStringTable = - FileNameRegistry.Infos[CurFilename].FilenameID; - // Each segment starts with the offset of the filename - // in the string table. - Asm->OutStreamer->AddComment( - "Segment for file '" + Twine(CurFilename) + "' begins"); - MCSymbol *FileSegmentBegin = Asm->MMI->getContext().createTempSymbol(); - Asm->OutStreamer->EmitLabel(FileSegmentBegin); - Asm->EmitInt32(8 * IndexInStringTable); - - // Number of PC records in the lookup table. - size_t SegmentLength = FilenameSegmentLengths[J]; - Asm->EmitInt32(SegmentLength); - - // Full size of the segment for this filename, including the prev two - // records. - FileSegmentEnd = Asm->MMI->getContext().createTempSymbol(); - EmitLabelDiff(*Asm->OutStreamer, FileSegmentBegin, FileSegmentEnd); - LastSegmentStart = J; - } - - // The first PC with the given linenumber and the linenumber itself. - EmitLabelDiff(*Asm->OutStreamer, Fn, Instr); - uint32_t LineNumber = InstrInfo[Instr].LineNumber; - assert(LineNumber <= COFF::CVL_MaxLineNumber); - uint32_t LineData = LineNumber | COFF::CVL_IsStatement; - Asm->EmitInt32(LineData); - } - - FinishPreviousChunk(); - Asm->OutStreamer->EmitLabel(LineTableEnd); -} - -void WinCodeViewLineTables::beginFunction(const MachineFunction *MF) { - assert(!CurFn && "Can't process two functions at once!"); - - if (!Asm || !Asm->MMI->hasDebugInfo()) - return; - - const Function *GV = MF->getFunction(); - assert(FnDebugInfo.count(GV) == false); - VisitedFunctions.push_back(GV); - CurFn = &FnDebugInfo[GV]; - - // Find the end of the function prolog. - // FIXME: is there a simpler a way to do this? Can we just search - // for the first instruction of the function, not the last of the prolog? - DebugLoc PrologEndLoc; - bool EmptyPrologue = true; - for (const auto &MBB : *MF) { - if (PrologEndLoc) - break; - for (const auto &MI : MBB) { - if (MI.isDebugValue()) - continue; - - // First known non-DBG_VALUE and non-frame setup location marks - // the beginning of the function body. - // FIXME: do we need the first subcondition? - if (!MI.getFlag(MachineInstr::FrameSetup) && MI.getDebugLoc()) { - PrologEndLoc = MI.getDebugLoc(); - break; - } - EmptyPrologue = false; - } - } - // Record beginning of function if we have a non-empty prologue. - if (PrologEndLoc && !EmptyPrologue) { - DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc(); - maybeRecordLocation(FnStartDL, MF); - } -} - -void WinCodeViewLineTables::endFunction(const MachineFunction *MF) { - if (!Asm || !CurFn) // We haven't created any debug info for this function. - return; - - const Function *GV = MF->getFunction(); - assert(FnDebugInfo.count(GV)); - assert(CurFn == &FnDebugInfo[GV]); - - if (CurFn->Instrs.empty()) { - FnDebugInfo.erase(GV); - VisitedFunctions.pop_back(); - } else { - CurFn->End = Asm->getFunctionEnd(); - } - CurFn = nullptr; -} - -void WinCodeViewLineTables::beginInstruction(const MachineInstr *MI) { - // Ignore DBG_VALUE locations and function prologue. - if (!Asm || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup)) - return; - DebugLoc DL = MI->getDebugLoc(); - if (DL == PrevInstLoc || !DL) - return; - maybeRecordLocation(DL, Asm->MF); -} -} diff --git a/gnu/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h b/gnu/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h deleted file mode 100644 index 78068e07c16..00000000000 --- a/gnu/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h +++ /dev/null @@ -1,138 +0,0 @@ -//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h ----*- C++ -*--===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains support for writing line tables info into COFF files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H -#define LLVM_LIB_CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H - -#include "AsmPrinterHandler.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/LexicalScopes.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/Target/TargetLoweringObjectFile.h" - -namespace llvm { -/// \brief Collects and handles line tables information in a CodeView format. -class LLVM_LIBRARY_VISIBILITY WinCodeViewLineTables : public AsmPrinterHandler { - AsmPrinter *Asm; - DebugLoc PrevInstLoc; - - // For each function, store a vector of labels to its instructions, as well as - // to the end of the function. - struct FunctionInfo { - SmallVector<MCSymbol *, 10> Instrs; - MCSymbol *End; - FunctionInfo() : End(nullptr) {} - } *CurFn; - - typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy; - FnDebugInfoTy FnDebugInfo; - // Store the functions we've visited in a vector so we can maintain a stable - // order while emitting subsections. - SmallVector<const Function *, 10> VisitedFunctions; - - // InstrInfoTy - Holds the Filename:LineNumber information for every - // instruction with a unique debug location. - struct InstrInfoTy { - StringRef Filename; - unsigned LineNumber; - unsigned ColumnNumber; - - InstrInfoTy() : LineNumber(0), ColumnNumber(0) {} - - InstrInfoTy(StringRef Filename, unsigned LineNumber, unsigned ColumnNumber) - : Filename(Filename), LineNumber(LineNumber), - ColumnNumber(ColumnNumber) {} - }; - DenseMap<MCSymbol *, InstrInfoTy> InstrInfo; - - // FileNameRegistry - Manages filenames observed while generating debug info - // by filtering out duplicates and bookkeeping the offsets in the string - // table to be generated. - struct FileNameRegistryTy { - SmallVector<StringRef, 10> Filenames; - struct PerFileInfo { - size_t FilenameID, StartOffset; - }; - StringMap<PerFileInfo> Infos; - - // The offset in the string table where we'll write the next unique - // filename. - size_t LastOffset; - - FileNameRegistryTy() { - clear(); - } - - // Add Filename to the registry, if it was not observed before. - void add(StringRef Filename) { - if (Infos.count(Filename)) - return; - size_t OldSize = Infos.size(); - Infos[Filename].FilenameID = OldSize; - Infos[Filename].StartOffset = LastOffset; - LastOffset += Filename.size() + 1; - Filenames.push_back(Filename); - } - - void clear() { - LastOffset = 1; - Infos.clear(); - Filenames.clear(); - } - } FileNameRegistry; - - typedef std::map<std::pair<StringRef, StringRef>, std::string> - DirAndFilenameToFilepathMapTy; - DirAndFilenameToFilepathMapTy DirAndFilenameToFilepathMap; - StringRef getFullFilepath(const MDNode *S); - - void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF); - - void clear() { - assert(CurFn == nullptr); - FileNameRegistry.clear(); - InstrInfo.clear(); - } - - void emitDebugInfoForFunction(const Function *GV); - -public: - WinCodeViewLineTables(AsmPrinter *Asm); - - void setSymbolSize(const llvm::MCSymbol *, uint64_t) override {} - - /// \brief Emit the COFF section that holds the line table information. - void endModule() override; - - /// \brief Gather pre-function debug information. - void beginFunction(const MachineFunction *MF) override; - - /// \brief Gather post-function debug information. - void endFunction(const MachineFunction *) override; - - /// \brief Process beginning of an instruction. - void beginInstruction(const MachineInstr *MI) override; - - /// \brief Process end of an instruction. - void endInstruction() override {} -}; -} // End of namespace llvm - -#endif diff --git a/gnu/llvm/lib/CodeGen/CoreCLRGC.cpp b/gnu/llvm/lib/CodeGen/CoreCLRGC.cpp deleted file mode 100644 index ff7c0d5dc0a..00000000000 --- a/gnu/llvm/lib/CodeGen/CoreCLRGC.cpp +++ /dev/null @@ -1,54 +0,0 @@ -//===-- CoreCLRGC.cpp - CoreCLR Runtime GC Strategy -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains a GCStrategy for the CoreCLR Runtime. -// The strategy is similar to Statepoint-example GC, but differs from it in -// certain aspects, such as: -// 1) Base-pointers need not be explicitly tracked and reported for -// interior pointers -// 2) Uses a different format for encoding stack-maps -// 3) Location of Safe-point polls: polls are only needed before loop-back edges -// and before tail-calls (not needed at function-entry) -// -// The above differences in behavior are to be implemented in upcoming checkins. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/GCStrategy.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Value.h" - -using namespace llvm; - -namespace { -class CoreCLRGC : public GCStrategy { -public: - CoreCLRGC() { - UseStatepoints = true; - // These options are all gc.root specific, we specify them so that the - // gc.root lowering code doesn't run. - InitRoots = false; - NeededSafePoints = 0; - UsesMetadata = false; - CustomRoots = false; - } - Optional<bool> isGCManagedPointer(const Type *Ty) const override { - // Method is only valid on pointer typed values. - const PointerType *PT = cast<PointerType>(Ty); - // We pick addrspace(1) as our GC managed heap. - return (1 == PT->getAddressSpace()); - } -}; -} - -static GCRegistry::Add<CoreCLRGC> X("coreclr", "CoreCLR-compatible GC"); - -namespace llvm { -void linkCoreCLRGC() {} -} diff --git a/gnu/llvm/lib/CodeGen/ErlangGC.cpp b/gnu/llvm/lib/CodeGen/ErlangGC.cpp deleted file mode 100644 index 024946d1436..00000000000 --- a/gnu/llvm/lib/CodeGen/ErlangGC.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===-- ErlangGC.cpp - Erlang/OTP GC strategy -------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the Erlang/OTP runtime-compatible garbage collector -// (e.g. defines safe points, root initialization etc.) -// -// The frametable emitter is in ErlangGCPrinter.cpp. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/GCs.h" -#include "llvm/CodeGen/GCStrategy.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetSubtargetInfo.h" - -using namespace llvm; - -namespace { - -class ErlangGC : public GCStrategy { -public: - ErlangGC(); -}; -} - -static GCRegistry::Add<ErlangGC> X("erlang", - "erlang-compatible garbage collector"); - -void llvm::linkErlangGC() {} - -ErlangGC::ErlangGC() { - InitRoots = false; - NeededSafePoints = 1 << GC::PostCall; - UsesMetadata = true; - CustomRoots = false; -} diff --git a/gnu/llvm/lib/CodeGen/MIRParser/Makefile b/gnu/llvm/lib/CodeGen/MIRParser/Makefile deleted file mode 100644 index c02d18806a9..00000000000 --- a/gnu/llvm/lib/CodeGen/MIRParser/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/CodeGen/MIRParser/Makefile ----------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMMIRParser - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/CodeGen/Makefile b/gnu/llvm/lib/CodeGen/Makefile deleted file mode 100644 index 96f7ca58513..00000000000 --- a/gnu/llvm/lib/CodeGen/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -##===- lib/CodeGen/Makefile --------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMCodeGen -PARALLEL_DIRS = SelectionDAG AsmPrinter MIRParser -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - -# Xcode prior to 2.4 generates an error in -pedantic mode with use of HUGE_VAL -# in this directory. Disable -pedantic for this broken compiler. -ifneq ($(HUGE_VAL_SANITY),yes) -CompileCommonOpts := $(filter-out -pedantic, $(CompileCommonOpts)) -endif - diff --git a/gnu/llvm/lib/CodeGen/OcamlGC.cpp b/gnu/llvm/lib/CodeGen/OcamlGC.cpp deleted file mode 100644 index 17654a6ac3a..00000000000 --- a/gnu/llvm/lib/CodeGen/OcamlGC.cpp +++ /dev/null @@ -1,36 +0,0 @@ -//===-- OcamlGC.cpp - Ocaml frametable GC strategy ------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements lowering for the llvm.gc* intrinsics compatible with -// Objective Caml 3.10.0, which uses a liveness-accurate static stack map. -// -// The frametable emitter is in OcamlGCPrinter.cpp. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/GCs.h" -#include "llvm/CodeGen/GCStrategy.h" - -using namespace llvm; - -namespace { -class OcamlGC : public GCStrategy { -public: - OcamlGC(); -}; -} - -static GCRegistry::Add<OcamlGC> X("ocaml", "ocaml 3.10-compatible GC"); - -void llvm::linkOcamlGC() {} - -OcamlGC::OcamlGC() { - NeededSafePoints = 1 << GC::PostCall; - UsesMetadata = true; -} diff --git a/gnu/llvm/lib/CodeGen/Passes.cpp b/gnu/llvm/lib/CodeGen/Passes.cpp deleted file mode 100644 index 873f7125b82..00000000000 --- a/gnu/llvm/lib/CodeGen/Passes.cpp +++ /dev/null @@ -1,817 +0,0 @@ -//===-- Passes.cpp - Target independent code generation passes ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines interfaces to access the target independent code -// generation passes provided by the LLVM backend. -// -//===---------------------------------------------------------------------===// - -#include "llvm/CodeGen/Passes.h" -#include "llvm/Analysis/BasicAliasAnalysis.h" -#include "llvm/Analysis/CFLAliasAnalysis.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/ScopedNoAliasAA.h" -#include "llvm/Analysis/TypeBasedAliasAnalysis.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/RegAllocRegistry.h" -#include "llvm/IR/IRPrintingPasses.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Instrumentation.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/SymbolRewriter.h" - -using namespace llvm; - -static cl::opt<bool> DisablePostRA("disable-post-ra", cl::Hidden, - cl::desc("Disable Post Regalloc")); -static cl::opt<bool> DisableBranchFold("disable-branch-fold", cl::Hidden, - cl::desc("Disable branch folding")); -static cl::opt<bool> DisableTailDuplicate("disable-tail-duplicate", cl::Hidden, - cl::desc("Disable tail duplication")); -static cl::opt<bool> DisableEarlyTailDup("disable-early-taildup", cl::Hidden, - cl::desc("Disable pre-register allocation tail duplication")); -static cl::opt<bool> DisableBlockPlacement("disable-block-placement", - cl::Hidden, cl::desc("Disable probability-driven block placement")); -static cl::opt<bool> EnableBlockPlacementStats("enable-block-placement-stats", - cl::Hidden, cl::desc("Collect probability-driven block placement stats")); -static cl::opt<bool> DisableSSC("disable-ssc", cl::Hidden, - cl::desc("Disable Stack Slot Coloring")); -static cl::opt<bool> DisableMachineDCE("disable-machine-dce", cl::Hidden, - cl::desc("Disable Machine Dead Code Elimination")); -static cl::opt<bool> DisableEarlyIfConversion("disable-early-ifcvt", cl::Hidden, - cl::desc("Disable Early If-conversion")); -static cl::opt<bool> DisableMachineLICM("disable-machine-licm", cl::Hidden, - cl::desc("Disable Machine LICM")); -static cl::opt<bool> DisableMachineCSE("disable-machine-cse", cl::Hidden, - cl::desc("Disable Machine Common Subexpression Elimination")); -static cl::opt<cl::boolOrDefault> OptimizeRegAlloc( - "optimize-regalloc", cl::Hidden, - cl::desc("Enable optimized register allocation compilation path.")); -static cl::opt<bool> DisablePostRAMachineLICM("disable-postra-machine-licm", - cl::Hidden, - cl::desc("Disable Machine LICM")); -static cl::opt<bool> DisableMachineSink("disable-machine-sink", cl::Hidden, - cl::desc("Disable Machine Sinking")); -static cl::opt<bool> DisableLSR("disable-lsr", cl::Hidden, - cl::desc("Disable Loop Strength Reduction Pass")); -static cl::opt<bool> DisableConstantHoisting("disable-constant-hoisting", - cl::Hidden, cl::desc("Disable ConstantHoisting")); -static cl::opt<bool> DisableCGP("disable-cgp", cl::Hidden, - cl::desc("Disable Codegen Prepare")); -static cl::opt<bool> DisableCopyProp("disable-copyprop", cl::Hidden, - cl::desc("Disable Copy Propagation pass")); -static cl::opt<bool> DisablePartialLibcallInlining("disable-partial-libcall-inlining", - cl::Hidden, cl::desc("Disable Partial Libcall Inlining")); -static cl::opt<bool> EnableImplicitNullChecks( - "enable-implicit-null-checks", - cl::desc("Fold null checks into faulting memory operations"), - cl::init(false)); -static cl::opt<bool> PrintLSR("print-lsr-output", cl::Hidden, - cl::desc("Print LLVM IR produced by the loop-reduce pass")); -static cl::opt<bool> PrintISelInput("print-isel-input", cl::Hidden, - cl::desc("Print LLVM IR input to isel pass")); -static cl::opt<bool> PrintGCInfo("print-gc", cl::Hidden, - cl::desc("Dump garbage collector data")); -static cl::opt<bool> VerifyMachineCode("verify-machineinstrs", cl::Hidden, - cl::desc("Verify generated machine code"), - cl::init(false), - cl::ZeroOrMore); - -static cl::opt<std::string> -PrintMachineInstrs("print-machineinstrs", cl::ValueOptional, - cl::desc("Print machine instrs"), - cl::value_desc("pass-name"), cl::init("option-unspecified")); - -// Temporary option to allow experimenting with MachineScheduler as a post-RA -// scheduler. Targets can "properly" enable this with -// substitutePass(&PostRASchedulerID, &PostMachineSchedulerID). -// Targets can return true in targetSchedulesPostRAScheduling() and -// insert a PostRA scheduling pass wherever it wants. -cl::opt<bool> MISchedPostRA("misched-postra", cl::Hidden, - cl::desc("Run MachineScheduler post regalloc (independent of preRA sched)")); - -// Experimental option to run live interval analysis early. -static cl::opt<bool> EarlyLiveIntervals("early-live-intervals", cl::Hidden, - cl::desc("Run live interval analysis earlier in the pipeline")); - -static cl::opt<bool> UseCFLAA("use-cfl-aa-in-codegen", - cl::init(false), cl::Hidden, - cl::desc("Enable the new, experimental CFL alias analysis in CodeGen")); - -/// Allow standard passes to be disabled by command line options. This supports -/// simple binary flags that either suppress the pass or do nothing. -/// i.e. -disable-mypass=false has no effect. -/// These should be converted to boolOrDefault in order to use applyOverride. -static IdentifyingPassPtr applyDisable(IdentifyingPassPtr PassID, - bool Override) { - if (Override) - return IdentifyingPassPtr(); - return PassID; -} - -/// Allow standard passes to be disabled by the command line, regardless of who -/// is adding the pass. -/// -/// StandardID is the pass identified in the standard pass pipeline and provided -/// to addPass(). It may be a target-specific ID in the case that the target -/// directly adds its own pass, but in that case we harmlessly fall through. -/// -/// TargetID is the pass that the target has configured to override StandardID. -/// -/// StandardID may be a pseudo ID. In that case TargetID is the name of the real -/// pass to run. This allows multiple options to control a single pass depending -/// on where in the pipeline that pass is added. -static IdentifyingPassPtr overridePass(AnalysisID StandardID, - IdentifyingPassPtr TargetID) { - if (StandardID == &PostRASchedulerID) - return applyDisable(TargetID, DisablePostRA); - - if (StandardID == &BranchFolderPassID) - return applyDisable(TargetID, DisableBranchFold); - - if (StandardID == &TailDuplicateID) - return applyDisable(TargetID, DisableTailDuplicate); - - if (StandardID == &TargetPassConfig::EarlyTailDuplicateID) - return applyDisable(TargetID, DisableEarlyTailDup); - - if (StandardID == &MachineBlockPlacementID) - return applyDisable(TargetID, DisableBlockPlacement); - - if (StandardID == &StackSlotColoringID) - return applyDisable(TargetID, DisableSSC); - - if (StandardID == &DeadMachineInstructionElimID) - return applyDisable(TargetID, DisableMachineDCE); - - if (StandardID == &EarlyIfConverterID) - return applyDisable(TargetID, DisableEarlyIfConversion); - - if (StandardID == &MachineLICMID) - return applyDisable(TargetID, DisableMachineLICM); - - if (StandardID == &MachineCSEID) - return applyDisable(TargetID, DisableMachineCSE); - - if (StandardID == &TargetPassConfig::PostRAMachineLICMID) - return applyDisable(TargetID, DisablePostRAMachineLICM); - - if (StandardID == &MachineSinkingID) - return applyDisable(TargetID, DisableMachineSink); - - if (StandardID == &MachineCopyPropagationID) - return applyDisable(TargetID, DisableCopyProp); - - return TargetID; -} - -//===---------------------------------------------------------------------===// -/// TargetPassConfig -//===---------------------------------------------------------------------===// - -INITIALIZE_PASS(TargetPassConfig, "targetpassconfig", - "Target Pass Configuration", false, false) -char TargetPassConfig::ID = 0; - -// Pseudo Pass IDs. -char TargetPassConfig::EarlyTailDuplicateID = 0; -char TargetPassConfig::PostRAMachineLICMID = 0; - -namespace { -struct InsertedPass { - AnalysisID TargetPassID; - IdentifyingPassPtr InsertedPassID; - bool VerifyAfter; - bool PrintAfter; - - InsertedPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID, - bool VerifyAfter, bool PrintAfter) - : TargetPassID(TargetPassID), InsertedPassID(InsertedPassID), - VerifyAfter(VerifyAfter), PrintAfter(PrintAfter) {} - - Pass *getInsertedPass() const { - assert(InsertedPassID.isValid() && "Illegal Pass ID!"); - if (InsertedPassID.isInstance()) - return InsertedPassID.getInstance(); - Pass *NP = Pass::createPass(InsertedPassID.getID()); - assert(NP && "Pass ID not registered"); - return NP; - } -}; -} - -namespace llvm { -class PassConfigImpl { -public: - // List of passes explicitly substituted by this target. Normally this is - // empty, but it is a convenient way to suppress or replace specific passes - // that are part of a standard pass pipeline without overridding the entire - // pipeline. This mechanism allows target options to inherit a standard pass's - // user interface. For example, a target may disable a standard pass by - // default by substituting a pass ID of zero, and the user may still enable - // that standard pass with an explicit command line option. - DenseMap<AnalysisID,IdentifyingPassPtr> TargetPasses; - - /// Store the pairs of <AnalysisID, AnalysisID> of which the second pass - /// is inserted after each instance of the first one. - SmallVector<InsertedPass, 4> InsertedPasses; -}; -} // namespace llvm - -// Out of line virtual method. -TargetPassConfig::~TargetPassConfig() { - delete Impl; -} - -// Out of line constructor provides default values for pass options and -// registers all common codegen passes. -TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm) - : ImmutablePass(ID), PM(&pm), StartBefore(nullptr), StartAfter(nullptr), - StopAfter(nullptr), Started(true), Stopped(false), - AddingMachinePasses(false), TM(tm), Impl(nullptr), Initialized(false), - DisableVerify(false), EnableTailMerge(true) { - - Impl = new PassConfigImpl(); - - // Register all target independent codegen passes to activate their PassIDs, - // including this pass itself. - initializeCodeGen(*PassRegistry::getPassRegistry()); - - // Also register alias analysis passes required by codegen passes. - initializeBasicAAWrapperPassPass(*PassRegistry::getPassRegistry()); - initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry()); - - // Substitute Pseudo Pass IDs for real ones. - substitutePass(&EarlyTailDuplicateID, &TailDuplicateID); - substitutePass(&PostRAMachineLICMID, &MachineLICMID); -} - -/// Insert InsertedPassID pass after TargetPassID. -void TargetPassConfig::insertPass(AnalysisID TargetPassID, - IdentifyingPassPtr InsertedPassID, - bool VerifyAfter, bool PrintAfter) { - assert(((!InsertedPassID.isInstance() && - TargetPassID != InsertedPassID.getID()) || - (InsertedPassID.isInstance() && - TargetPassID != InsertedPassID.getInstance()->getPassID())) && - "Insert a pass after itself!"); - Impl->InsertedPasses.emplace_back(TargetPassID, InsertedPassID, VerifyAfter, - PrintAfter); -} - -/// createPassConfig - Create a pass configuration object to be used by -/// addPassToEmitX methods for generating a pipeline of CodeGen passes. -/// -/// Targets may override this to extend TargetPassConfig. -TargetPassConfig *LLVMTargetMachine::createPassConfig(PassManagerBase &PM) { - return new TargetPassConfig(this, PM); -} - -TargetPassConfig::TargetPassConfig() - : ImmutablePass(ID), PM(nullptr) { - llvm_unreachable("TargetPassConfig should not be constructed on-the-fly"); -} - -// Helper to verify the analysis is really immutable. -void TargetPassConfig::setOpt(bool &Opt, bool Val) { - assert(!Initialized && "PassConfig is immutable"); - Opt = Val; -} - -void TargetPassConfig::substitutePass(AnalysisID StandardID, - IdentifyingPassPtr TargetID) { - Impl->TargetPasses[StandardID] = TargetID; -} - -IdentifyingPassPtr TargetPassConfig::getPassSubstitution(AnalysisID ID) const { - DenseMap<AnalysisID, IdentifyingPassPtr>::const_iterator - I = Impl->TargetPasses.find(ID); - if (I == Impl->TargetPasses.end()) - return ID; - return I->second; -} - -/// Add a pass to the PassManager if that pass is supposed to be run. If the -/// Started/Stopped flags indicate either that the compilation should start at -/// a later pass or that it should stop after an earlier pass, then do not add -/// the pass. Finally, compare the current pass against the StartAfter -/// and StopAfter options and change the Started/Stopped flags accordingly. -void TargetPassConfig::addPass(Pass *P, bool verifyAfter, bool printAfter) { - assert(!Initialized && "PassConfig is immutable"); - - // Cache the Pass ID here in case the pass manager finds this pass is - // redundant with ones already scheduled / available, and deletes it. - // Fundamentally, once we add the pass to the manager, we no longer own it - // and shouldn't reference it. - AnalysisID PassID = P->getPassID(); - - if (StartBefore == PassID) - Started = true; - if (Started && !Stopped) { - std::string Banner; - // Construct banner message before PM->add() as that may delete the pass. - if (AddingMachinePasses && (printAfter || verifyAfter)) - Banner = std::string("After ") + std::string(P->getPassName()); - PM->add(P); - if (AddingMachinePasses) { - if (printAfter) - addPrintPass(Banner); - if (verifyAfter) - addVerifyPass(Banner); - } - - // Add the passes after the pass P if there is any. - for (auto IP : Impl->InsertedPasses) { - if (IP.TargetPassID == PassID) - addPass(IP.getInsertedPass(), IP.VerifyAfter, IP.PrintAfter); - } - } else { - delete P; - } - if (StopAfter == PassID) - Stopped = true; - if (StartAfter == PassID) - Started = true; - if (Stopped && !Started) - report_fatal_error("Cannot stop compilation after pass that is not run"); -} - -/// Add a CodeGen pass at this point in the pipeline after checking for target -/// and command line overrides. -/// -/// addPass cannot return a pointer to the pass instance because is internal the -/// PassManager and the instance we create here may already be freed. -AnalysisID TargetPassConfig::addPass(AnalysisID PassID, bool verifyAfter, - bool printAfter) { - IdentifyingPassPtr TargetID = getPassSubstitution(PassID); - IdentifyingPassPtr FinalPtr = overridePass(PassID, TargetID); - if (!FinalPtr.isValid()) - return nullptr; - - Pass *P; - if (FinalPtr.isInstance()) - P = FinalPtr.getInstance(); - else { - P = Pass::createPass(FinalPtr.getID()); - if (!P) - llvm_unreachable("Pass ID not registered"); - } - AnalysisID FinalID = P->getPassID(); - addPass(P, verifyAfter, printAfter); // Ends the lifetime of P. - - return FinalID; -} - -void TargetPassConfig::printAndVerify(const std::string &Banner) { - addPrintPass(Banner); - addVerifyPass(Banner); -} - -void TargetPassConfig::addPrintPass(const std::string &Banner) { - if (TM->shouldPrintMachineCode()) - PM->add(createMachineFunctionPrinterPass(dbgs(), Banner)); -} - -void TargetPassConfig::addVerifyPass(const std::string &Banner) { - if (VerifyMachineCode) - PM->add(createMachineVerifierPass(Banner)); -} - -/// Add common target configurable passes that perform LLVM IR to IR transforms -/// following machine independent optimization. -void TargetPassConfig::addIRPasses() { - // Basic AliasAnalysis support. - // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that - // BasicAliasAnalysis wins if they disagree. This is intended to help - // support "obvious" type-punning idioms. - if (UseCFLAA) - addPass(createCFLAAWrapperPass()); - addPass(createTypeBasedAAWrapperPass()); - addPass(createScopedNoAliasAAWrapperPass()); - addPass(createBasicAAWrapperPass()); - - // Before running any passes, run the verifier to determine if the input - // coming from the front-end and/or optimizer is valid. - if (!DisableVerify) - addPass(createVerifierPass()); - - // Run loop strength reduction before anything else. - if (getOptLevel() != CodeGenOpt::None && !DisableLSR) { - addPass(createLoopStrengthReducePass()); - if (PrintLSR) - addPass(createPrintFunctionPass(dbgs(), "\n\n*** Code after LSR ***\n")); - } - - // Run GC lowering passes for builtin collectors - // TODO: add a pass insertion point here - addPass(createGCLoweringPass()); - addPass(createShadowStackGCLoweringPass()); - - // Make sure that no unreachable blocks are instruction selected. - addPass(createUnreachableBlockEliminationPass()); - - // Prepare expensive constants for SelectionDAG. - if (getOptLevel() != CodeGenOpt::None && !DisableConstantHoisting) - addPass(createConstantHoistingPass()); - - if (getOptLevel() != CodeGenOpt::None && !DisablePartialLibcallInlining) - addPass(createPartiallyInlineLibCallsPass()); -} - -/// Turn exception handling constructs into something the code generators can -/// handle. -void TargetPassConfig::addPassesToHandleExceptions() { - switch (TM->getMCAsmInfo()->getExceptionHandlingType()) { - case ExceptionHandling::SjLj: - // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both - // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise, - // catch info can get misplaced when a selector ends up more than one block - // removed from the parent invoke(s). This could happen when a landing - // pad is shared by multiple invokes and is also a target of a normal - // edge from elsewhere. - addPass(createSjLjEHPreparePass()); - // FALLTHROUGH - case ExceptionHandling::DwarfCFI: - case ExceptionHandling::ARM: - addPass(createDwarfEHPass(TM)); - break; - case ExceptionHandling::WinEH: - // We support using both GCC-style and MSVC-style exceptions on Windows, so - // add both preparation passes. Each pass will only actually run if it - // recognizes the personality function. - addPass(createWinEHPass(TM)); - addPass(createDwarfEHPass(TM)); - break; - case ExceptionHandling::None: - addPass(createLowerInvokePass()); - - // The lower invoke pass may create unreachable code. Remove it. - addPass(createUnreachableBlockEliminationPass()); - break; - } -} - -/// Add pass to prepare the LLVM IR for code generation. This should be done -/// before exception handling preparation passes. -void TargetPassConfig::addCodeGenPrepare() { - if (getOptLevel() != CodeGenOpt::None && !DisableCGP) - addPass(createCodeGenPreparePass(TM)); - addPass(createRewriteSymbolsPass()); -} - -/// Add common passes that perform LLVM IR to IR transforms in preparation for -/// instruction selection. -void TargetPassConfig::addISelPrepare() { - addPreISel(); - - // Add both the safe stack and the stack protection passes: each of them will - // only protect functions that have corresponding attributes. - addPass(createSafeStackPass(TM)); - addPass(createStackProtectorPass(TM)); - - if (PrintISelInput) - addPass(createPrintFunctionPass( - dbgs(), "\n\n*** Final LLVM Code input to ISel ***\n")); - - // All passes which modify the LLVM IR are now complete; run the verifier - // to ensure that the IR is valid. - if (!DisableVerify) - addPass(createVerifierPass()); -} - -/// Add the complete set of target-independent postISel code generator passes. -/// -/// This can be read as the standard order of major LLVM CodeGen stages. Stages -/// with nontrivial configuration or multiple passes are broken out below in -/// add%Stage routines. -/// -/// Any TargetPassConfig::addXX routine may be overriden by the Target. The -/// addPre/Post methods with empty header implementations allow injecting -/// target-specific fixups just before or after major stages. Additionally, -/// targets have the flexibility to change pass order within a stage by -/// overriding default implementation of add%Stage routines below. Each -/// technique has maintainability tradeoffs because alternate pass orders are -/// not well supported. addPre/Post works better if the target pass is easily -/// tied to a common pass. But if it has subtle dependencies on multiple passes, -/// the target should override the stage instead. -/// -/// TODO: We could use a single addPre/Post(ID) hook to allow pass injection -/// before/after any target-independent pass. But it's currently overkill. -void TargetPassConfig::addMachinePasses() { - AddingMachinePasses = true; - - // Insert a machine instr printer pass after the specified pass. - // If -print-machineinstrs specified, print machineinstrs after all passes. - if (StringRef(PrintMachineInstrs.getValue()).equals("")) - TM->Options.PrintMachineCode = true; - else if (!StringRef(PrintMachineInstrs.getValue()) - .equals("option-unspecified")) { - const PassRegistry *PR = PassRegistry::getPassRegistry(); - const PassInfo *TPI = PR->getPassInfo(PrintMachineInstrs.getValue()); - const PassInfo *IPI = PR->getPassInfo(StringRef("machineinstr-printer")); - assert (TPI && IPI && "Pass ID not registered!"); - const char *TID = (const char *)(TPI->getTypeInfo()); - const char *IID = (const char *)(IPI->getTypeInfo()); - insertPass(TID, IID); - } - - // Print the instruction selected machine code... - printAndVerify("After Instruction Selection"); - - // Expand pseudo-instructions emitted by ISel. - addPass(&ExpandISelPseudosID); - - // Add passes that optimize machine instructions in SSA form. - if (getOptLevel() != CodeGenOpt::None) { - addMachineSSAOptimization(); - } else { - // If the target requests it, assign local variables to stack slots relative - // to one another and simplify frame index references where possible. - addPass(&LocalStackSlotAllocationID, false); - } - - // Run pre-ra passes. - addPreRegAlloc(); - - // Run register allocation and passes that are tightly coupled with it, - // including phi elimination and scheduling. - if (getOptimizeRegAlloc()) - addOptimizedRegAlloc(createRegAllocPass(true)); - else - addFastRegAlloc(createRegAllocPass(false)); - - // Run post-ra passes. - addPostRegAlloc(); - - // Insert prolog/epilog code. Eliminate abstract frame index references... - if (getOptLevel() != CodeGenOpt::None) - addPass(&ShrinkWrapID); - - addPass(&PrologEpilogCodeInserterID); - - /// Add passes that optimize machine instructions after register allocation. - if (getOptLevel() != CodeGenOpt::None) - addMachineLateOptimization(); - - // Expand pseudo instructions before second scheduling pass. - addPass(&ExpandPostRAPseudosID); - - // Run pre-sched2 passes. - addPreSched2(); - - if (EnableImplicitNullChecks) - addPass(&ImplicitNullChecksID); - - // Second pass scheduler. - // Let Target optionally insert this pass by itself at some other - // point. - if (getOptLevel() != CodeGenOpt::None && - !TM->targetSchedulesPostRAScheduling()) { - if (MISchedPostRA) - addPass(&PostMachineSchedulerID); - else - addPass(&PostRASchedulerID); - } - - // GC - if (addGCPasses()) { - if (PrintGCInfo) - addPass(createGCInfoPrinter(dbgs()), false, false); - } - - // Basic block placement. - if (getOptLevel() != CodeGenOpt::None) - addBlockPlacement(); - - addPreEmitPass(); - - addPass(&FuncletLayoutID, false); - - addPass(&StackMapLivenessID, false); - addPass(&LiveDebugValuesID, false); - - AddingMachinePasses = false; -} - -/// Add passes that optimize machine instructions in SSA form. -void TargetPassConfig::addMachineSSAOptimization() { - // Pre-ra tail duplication. - addPass(&EarlyTailDuplicateID); - - // Optimize PHIs before DCE: removing dead PHI cycles may make more - // instructions dead. - addPass(&OptimizePHIsID, false); - - // This pass merges large allocas. StackSlotColoring is a different pass - // which merges spill slots. - addPass(&StackColoringID, false); - - // If the target requests it, assign local variables to stack slots relative - // to one another and simplify frame index references where possible. - addPass(&LocalStackSlotAllocationID, false); - - // With optimization, dead code should already be eliminated. However - // there is one known exception: lowered code for arguments that are only - // used by tail calls, where the tail calls reuse the incoming stack - // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll). - addPass(&DeadMachineInstructionElimID); - - // Allow targets to insert passes that improve instruction level parallelism, - // like if-conversion. Such passes will typically need dominator trees and - // loop info, just like LICM and CSE below. - addILPOpts(); - - addPass(&MachineLICMID, false); - addPass(&MachineCSEID, false); - addPass(&MachineSinkingID); - - addPass(&PeepholeOptimizerID); - // Clean-up the dead code that may have been generated by peephole - // rewriting. - addPass(&DeadMachineInstructionElimID); -} - -//===---------------------------------------------------------------------===// -/// Register Allocation Pass Configuration -//===---------------------------------------------------------------------===// - -bool TargetPassConfig::getOptimizeRegAlloc() const { - switch (OptimizeRegAlloc) { - case cl::BOU_UNSET: return getOptLevel() != CodeGenOpt::None; - case cl::BOU_TRUE: return true; - case cl::BOU_FALSE: return false; - } - llvm_unreachable("Invalid optimize-regalloc state"); -} - -/// RegisterRegAlloc's global Registry tracks allocator registration. -MachinePassRegistry RegisterRegAlloc::Registry; - -/// A dummy default pass factory indicates whether the register allocator is -/// overridden on the command line. -static FunctionPass *useDefaultRegisterAllocator() { return nullptr; } -static RegisterRegAlloc -defaultRegAlloc("default", - "pick register allocator based on -O option", - useDefaultRegisterAllocator); - -/// -regalloc=... command line option. -static cl::opt<RegisterRegAlloc::FunctionPassCtor, false, - RegisterPassParser<RegisterRegAlloc> > -RegAlloc("regalloc", - cl::init(&useDefaultRegisterAllocator), - cl::desc("Register allocator to use")); - - -/// Instantiate the default register allocator pass for this target for either -/// the optimized or unoptimized allocation path. This will be added to the pass -/// manager by addFastRegAlloc in the unoptimized case or addOptimizedRegAlloc -/// in the optimized case. -/// -/// A target that uses the standard regalloc pass order for fast or optimized -/// allocation may still override this for per-target regalloc -/// selection. But -regalloc=... always takes precedence. -FunctionPass *TargetPassConfig::createTargetRegisterAllocator(bool Optimized) { - if (Optimized) - return createGreedyRegisterAllocator(); - else - return createFastRegisterAllocator(); -} - -/// Find and instantiate the register allocation pass requested by this target -/// at the current optimization level. Different register allocators are -/// defined as separate passes because they may require different analysis. -/// -/// This helper ensures that the regalloc= option is always available, -/// even for targets that override the default allocator. -/// -/// FIXME: When MachinePassRegistry register pass IDs instead of function ptrs, -/// this can be folded into addPass. -FunctionPass *TargetPassConfig::createRegAllocPass(bool Optimized) { - RegisterRegAlloc::FunctionPassCtor Ctor = RegisterRegAlloc::getDefault(); - - // Initialize the global default. - if (!Ctor) { - Ctor = RegAlloc; - RegisterRegAlloc::setDefault(RegAlloc); - } - if (Ctor != useDefaultRegisterAllocator) - return Ctor(); - - // With no -regalloc= override, ask the target for a regalloc pass. - return createTargetRegisterAllocator(Optimized); -} - -/// Return true if the default global register allocator is in use and -/// has not be overriden on the command line with '-regalloc=...' -bool TargetPassConfig::usingDefaultRegAlloc() const { - return RegAlloc.getNumOccurrences() == 0; -} - -/// Add the minimum set of target-independent passes that are required for -/// register allocation. No coalescing or scheduling. -void TargetPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) { - addPass(&PHIEliminationID, false); - addPass(&TwoAddressInstructionPassID, false); - - if (RegAllocPass) - addPass(RegAllocPass); -} - -/// Add standard target-independent passes that are tightly coupled with -/// optimized register allocation, including coalescing, machine instruction -/// scheduling, and register allocation itself. -void TargetPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) { - addPass(&ProcessImplicitDefsID, false); - - // LiveVariables currently requires pure SSA form. - // - // FIXME: Once TwoAddressInstruction pass no longer uses kill flags, - // LiveVariables can be removed completely, and LiveIntervals can be directly - // computed. (We still either need to regenerate kill flags after regalloc, or - // preferably fix the scavenger to not depend on them). - addPass(&LiveVariablesID, false); - - // Edge splitting is smarter with machine loop info. - addPass(&MachineLoopInfoID, false); - addPass(&PHIEliminationID, false); - - // Eventually, we want to run LiveIntervals before PHI elimination. - if (EarlyLiveIntervals) - addPass(&LiveIntervalsID, false); - - addPass(&TwoAddressInstructionPassID, false); - addPass(&RegisterCoalescerID); - - // PreRA instruction scheduling. - addPass(&MachineSchedulerID); - - if (RegAllocPass) { - // Add the selected register allocation pass. - addPass(RegAllocPass); - - // Allow targets to change the register assignments before rewriting. - addPreRewrite(); - - // Finally rewrite virtual registers. - addPass(&VirtRegRewriterID); - - // Perform stack slot coloring and post-ra machine LICM. - // - // FIXME: Re-enable coloring with register when it's capable of adding - // kill markers. - addPass(&StackSlotColoringID); - - // Run post-ra machine LICM to hoist reloads / remats. - // - // FIXME: can this move into MachineLateOptimization? - addPass(&PostRAMachineLICMID); - } -} - -//===---------------------------------------------------------------------===// -/// Post RegAlloc Pass Configuration -//===---------------------------------------------------------------------===// - -/// Add passes that optimize machine instructions after register allocation. -void TargetPassConfig::addMachineLateOptimization() { - // Branch folding must be run after regalloc and prolog/epilog insertion. - addPass(&BranchFolderPassID); - - // Tail duplication. - // Note that duplicating tail just increases code size and degrades - // performance for targets that require Structured Control Flow. - // In addition it can also make CFG irreducible. Thus we disable it. - if (!TM->requiresStructuredCFG()) - addPass(&TailDuplicateID); - - // Copy propagation. - addPass(&MachineCopyPropagationID); -} - -/// Add standard GC passes. -bool TargetPassConfig::addGCPasses() { - addPass(&GCMachineCodeAnalysisID, false); - return true; -} - -/// Add standard basic block placement passes. -void TargetPassConfig::addBlockPlacement() { - if (addPass(&MachineBlockPlacementID, false)) { - // Run a separate pass to collect block placement statistics. - if (EnableBlockPlacementStats) - addPass(&MachineBlockPlacementStatsID); - } -} diff --git a/gnu/llvm/lib/CodeGen/SelectionDAG/Makefile b/gnu/llvm/lib/CodeGen/SelectionDAG/Makefile deleted file mode 100644 index ea716fdaabb..00000000000 --- a/gnu/llvm/lib/CodeGen/SelectionDAG/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/CodeGen/SelectionDAG/Makefile -------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMSelectionDAG - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/CodeGen/SelectionDAG/TargetSelectionDAGInfo.cpp b/gnu/llvm/lib/CodeGen/SelectionDAG/TargetSelectionDAGInfo.cpp deleted file mode 100644 index 00db9425684..00000000000 --- a/gnu/llvm/lib/CodeGen/SelectionDAG/TargetSelectionDAGInfo.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//===-- TargetSelectionDAGInfo.cpp - SelectionDAG Info --------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This implements the TargetSelectionDAGInfo class. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Target/TargetSelectionDAGInfo.h" -#include "llvm/Target/TargetMachine.h" -using namespace llvm; - -TargetSelectionDAGInfo::~TargetSelectionDAGInfo() { -} diff --git a/gnu/llvm/lib/CodeGen/ShadowStackGC.cpp b/gnu/llvm/lib/CodeGen/ShadowStackGC.cpp deleted file mode 100644 index b12e943eb35..00000000000 --- a/gnu/llvm/lib/CodeGen/ShadowStackGC.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//===-- ShadowStackGC.cpp - GC support for uncooperative targets ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements lowering for the llvm.gc* intrinsics for targets that do -// not natively support them (which includes the C backend). Note that the code -// generated is not quite as efficient as algorithms which generate stack maps -// to identify roots. -// -// This pass implements the code transformation described in this paper: -// "Accurate Garbage Collection in an Uncooperative Environment" -// Fergus Henderson, ISMM, 2002 -// -// In runtime/GC/SemiSpace.cpp is a prototype runtime which is compatible with -// ShadowStackGC. -// -// In order to support this particular transformation, all stack roots are -// coallocated in the stack. This allows a fully target-independent stack map -// while introducing only minor runtime overhead. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/GCs.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/CodeGen/GCStrategy.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Module.h" - -using namespace llvm; - -#define DEBUG_TYPE "shadowstackgc" - -namespace { -class ShadowStackGC : public GCStrategy { -public: - ShadowStackGC(); -}; -} - -static GCRegistry::Add<ShadowStackGC> - X("shadow-stack", "Very portable GC for uncooperative code generators"); - -void llvm::linkShadowStackGC() {} - -ShadowStackGC::ShadowStackGC() { - InitRoots = true; - CustomRoots = true; -} diff --git a/gnu/llvm/lib/CodeGen/StackProtector.cpp b/gnu/llvm/lib/CodeGen/StackProtector.cpp index d45d31ee0ae..89868e43aba 100644 --- a/gnu/llvm/lib/CodeGen/StackProtector.cpp +++ b/gnu/llvm/lib/CodeGen/StackProtector.cpp @@ -18,12 +18,13 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/BranchProbabilityInfo.h" +#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/ValueTracking.h" -#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" @@ -89,15 +90,25 @@ bool StackProtector::runOnFunction(Function &Fn) { getAnalysisIfAvailable<DominatorTreeWrapperPass>(); DT = DTWP ? &DTWP->getDomTree() : nullptr; TLI = TM->getSubtargetImpl(Fn)->getTargetLowering(); + HasPrologue = false; + HasIRCheck = false; Attribute Attr = Fn.getFnAttribute("stack-protector-buffer-size"); if (Attr.isStringAttribute() && Attr.getValueAsString().getAsInteger(10, SSPBufferSize)) - return false; // Invalid integer string + return false; // Invalid integer string if (!RequiresStackProtector()) return false; + // TODO(etienneb): Functions with funclets are not correctly supported now. + // Do nothing if this is funclet-based personality. + if (Fn.hasPersonalityFn()) { + EHPersonality Personality = classifyEHPersonality(Fn.getPersonalityFn()); + if (isFuncletEHPersonality(Personality)) + return false; + } + ++NumFunProtected; return InsertStackProtectors(); } @@ -200,11 +211,24 @@ bool StackProtector::HasAddressTaken(const Instruction *AI) { bool StackProtector::RequiresStackProtector() { bool Strong = false; bool NeedsProtector = false; + for (const BasicBlock &BB : *F) + for (const Instruction &I : BB) + if (const CallInst *CI = dyn_cast<CallInst>(&I)) + if (CI->getCalledFunction() == + Intrinsic::getDeclaration(F->getParent(), + Intrinsic::stackprotector)) + HasPrologue = true; + + if (F->hasFnAttribute(Attribute::SafeStack)) + return false; + if (F->hasFnAttribute(Attribute::StackProtectReq)) { NeedsProtector = true; Strong = true; // Use the same heuristic as strong to determine SSPLayout } else if (F->hasFnAttribute(Attribute::StackProtectStrong)) Strong = true; + else if (HasPrologue) + NeedsProtector = true; else if (!F->hasFnAttribute(Attribute::StackProtect)) return false; @@ -256,104 +280,51 @@ bool StackProtector::RequiresStackProtector() { return NeedsProtector; } -static bool InstructionWillNotHaveChain(const Instruction *I) { - return !I->mayHaveSideEffects() && !I->mayReadFromMemory() && - isSafeToSpeculativelyExecute(I); +/// Create a stack guard loading and populate whether SelectionDAG SSP is +/// supported. +static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M, + IRBuilder<> &B, + bool *SupportsSelectionDAGSP = nullptr) { + if (Value *Guard = TLI->getIRStackGuard(B)) + return B.CreateLoad(Guard, true, "StackGuard"); + + // Use SelectionDAG SSP handling, since there isn't an IR guard. + // + // This is more or less weird, since we optionally output whether we + // should perform a SelectionDAG SP here. The reason is that it's strictly + // defined as !TLI->getIRStackGuard(B), where getIRStackGuard is also + // mutating. There is no way to get this bit without mutating the IR, so + // getting this bit has to happen in this right time. + // + // We could have define a new function TLI::supportsSelectionDAGSP(), but that + // will put more burden on the backends' overriding work, especially when it + // actually conveys the same information getIRStackGuard() already gives. + if (SupportsSelectionDAGSP) + *SupportsSelectionDAGSP = true; + TLI->insertSSPDeclarations(*M); + return B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackguard)); } -/// Identify if RI has a previous instruction in the "Tail Position" and return -/// it. Otherwise return 0. -/// -/// This is based off of the code in llvm::isInTailCallPosition. The difference -/// is that it inverts the first part of llvm::isInTailCallPosition since -/// isInTailCallPosition is checking if a call is in a tail call position, and -/// we are searching for an unknown tail call that might be in the tail call -/// position. Once we find the call though, the code uses the same refactored -/// code, returnTypeIsEligibleForTailCall. -static CallInst *FindPotentialTailCall(BasicBlock *BB, ReturnInst *RI, - const TargetLoweringBase *TLI) { - // Establish a reasonable upper bound on the maximum amount of instructions we - // will look through to find a tail call. - unsigned SearchCounter = 0; - const unsigned MaxSearch = 4; - bool NoInterposingChain = true; - - for (BasicBlock::reverse_iterator I = std::next(BB->rbegin()), E = BB->rend(); - I != E && SearchCounter < MaxSearch; ++I) { - Instruction *Inst = &*I; - - // Skip over debug intrinsics and do not allow them to affect our MaxSearch - // counter. - if (isa<DbgInfoIntrinsic>(Inst)) - continue; - - // If we find a call and the following conditions are satisifed, then we - // have found a tail call that satisfies at least the target independent - // requirements of a tail call: - // - // 1. The call site has the tail marker. - // - // 2. The call site either will not cause the creation of a chain or if a - // chain is necessary there are no instructions in between the callsite and - // the call which would create an interposing chain. - // - // 3. The return type of the function does not impede tail call - // optimization. - if (CallInst *CI = dyn_cast<CallInst>(Inst)) { - if (CI->isTailCall() && - (InstructionWillNotHaveChain(CI) || NoInterposingChain) && - returnTypeIsEligibleForTailCall(BB->getParent(), CI, RI, *TLI)) - return CI; - } - - // If we did not find a call see if we have an instruction that may create - // an interposing chain. - NoInterposingChain = - NoInterposingChain && InstructionWillNotHaveChain(Inst); - - // Increment max search. - SearchCounter++; - } - - return nullptr; -} - -/// Insert code into the entry block that stores the __stack_chk_guard +/// Insert code into the entry block that stores the stack guard /// variable onto the stack: /// /// entry: /// StackGuardSlot = alloca i8* -/// StackGuard = load __stack_chk_guard -/// call void @llvm.stackprotect.create(StackGuard, StackGuardSlot) +/// StackGuard = <stack guard> +/// call void @llvm.stackprotector(StackGuard, StackGuardSlot) /// /// Returns true if the platform/triple supports the stackprotectorcreate pseudo /// node. static bool CreatePrologue(Function *F, Module *M, ReturnInst *RI, - const TargetLoweringBase *TLI, const Triple &TT, - AllocaInst *&AI, Value *&StackGuardVar) { + const TargetLoweringBase *TLI, AllocaInst *&AI) { bool SupportsSelectionDAGSP = false; - PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext()); - unsigned AddressSpace, Offset; - if (TLI->getStackCookieLocation(AddressSpace, Offset)) { - Constant *OffsetVal = - ConstantInt::get(Type::getInt32Ty(RI->getContext()), Offset); - - StackGuardVar = - ConstantExpr::getIntToPtr(OffsetVal, PointerType::get(PtrTy, - AddressSpace)); - } else if (TT.isOSOpenBSD()) - StackGuardVar = M->getOrInsertGlobal("__guard_local", PtrTy); - else { - SupportsSelectionDAGSP = true; - StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); - } - IRBuilder<> B(&F->getEntryBlock().front()); + PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext()); AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot"); - LoadInst *LI = B.CreateLoad(StackGuardVar, "StackGuard"); - B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackprotector), - {LI, AI}); + Value *GuardSlot = getStackGuard(TLI, M, B, &SupportsSelectionDAGSP); + B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackprotector), + {GuardSlot, AI}); return SupportsSelectionDAGSP; } @@ -364,11 +335,9 @@ static bool CreatePrologue(Function *F, Module *M, ReturnInst *RI, /// - The epilogue checks the value stored in the prologue against the original /// value. It calls __stack_chk_fail if they differ. bool StackProtector::InsertStackProtectors() { - bool HasPrologue = false; bool SupportsSelectionDAGSP = EnableSelectionDAGSP && !TM->Options.EnableFastISel; AllocaInst *AI = nullptr; // Place on stack that stores the stack guard. - Value *StackGuardVar = nullptr; // The stack guard variable. for (Function::iterator I = F->begin(), E = F->end(); I != E;) { BasicBlock *BB = &*I++; @@ -376,30 +345,36 @@ bool StackProtector::InsertStackProtectors() { if (!RI) continue; + // Generate prologue instrumentation if not already generated. if (!HasPrologue) { HasPrologue = true; - SupportsSelectionDAGSP &= - CreatePrologue(F, M, RI, TLI, Trip, AI, StackGuardVar); + SupportsSelectionDAGSP &= CreatePrologue(F, M, RI, TLI, AI); } - if (SupportsSelectionDAGSP) { - // Since we have a potential tail call, insert the special stack check - // intrinsic. - Instruction *InsertionPt = nullptr; - if (CallInst *CI = FindPotentialTailCall(BB, RI, TLI)) { - InsertionPt = CI; - } else { - InsertionPt = RI; - // At this point we know that BB has a return statement so it *DOES* - // have a terminator. - assert(InsertionPt != nullptr && - "BB must have a terminator instruction at this point."); - } - - Function *Intrinsic = - Intrinsic::getDeclaration(M, Intrinsic::stackprotectorcheck); - CallInst::Create(Intrinsic, StackGuardVar, "", InsertionPt); + // SelectionDAG based code generation. Nothing else needs to be done here. + // The epilogue instrumentation is postponed to SelectionDAG. + if (SupportsSelectionDAGSP) + break; + + // Set HasIRCheck to true, so that SelectionDAG will not generate its own + // version. SelectionDAG called 'shouldEmitSDCheck' to check whether + // instrumentation has already been generated. + HasIRCheck = true; + + // Generate epilogue instrumentation. The epilogue intrumentation can be + // function-based or inlined depending on which mechanism the target is + // providing. + if (Value* GuardCheck = TLI->getSSPStackGuardCheck(*M)) { + // Generate the function-based epilogue instrumentation. + // The target provides a guard check function, generate a call to it. + IRBuilder<> B(RI); + LoadInst *Guard = B.CreateLoad(AI, true, "Guard"); + CallInst *Call = B.CreateCall(GuardCheck, {Guard}); + llvm::Function *Function = cast<llvm::Function>(GuardCheck); + Call->setAttributes(Function->getAttributes()); + Call->setCallingConv(Function->getCallingConv()); } else { + // Generate the epilogue with inline instrumentation. // If we do not support SelectionDAG based tail calls, generate IR level // tail calls. // @@ -413,7 +388,7 @@ bool StackProtector::InsertStackProtectors() { // // return: // ... - // %1 = load __stack_chk_guard + // %1 = <stack guard> // %2 = load StackGuardSlot // %3 = cmp i1 %1, %2 // br i1 %3, label %SP_return, label %CallStackCheckFailBlk @@ -448,9 +423,9 @@ bool StackProtector::InsertStackProtectors() { // Generate the stack protector instructions in the old basic block. IRBuilder<> B(BB); - LoadInst *LI1 = B.CreateLoad(StackGuardVar); - LoadInst *LI2 = B.CreateLoad(AI); - Value *Cmp = B.CreateICmpEQ(LI1, LI2); + Value *Guard = getStackGuard(TLI, M, B); + LoadInst *LI2 = B.CreateLoad(AI, true); + Value *Cmp = B.CreateICmpEQ(Guard, LI2); auto SuccessProb = BranchProbabilityInfo::getBranchProbStackProtector(true); auto FailureProb = @@ -473,6 +448,7 @@ BasicBlock *StackProtector::CreateFailBB() { LLVMContext &Context = F->getContext(); BasicBlock *FailBB = BasicBlock::Create(Context, "CallStackCheckFailBlk", F); IRBuilder<> B(FailBB); + B.SetCurrentDebugLocation(DebugLoc::get(0, 0, F->getSubprogram())); if (Trip.isOSOpenBSD()) { Constant *StackChkFail = M->getOrInsertFunction("__stack_smash_handler", @@ -489,3 +465,7 @@ BasicBlock *StackProtector::CreateFailBB() { B.CreateUnreachable(); return FailBB; } + +bool StackProtector::shouldEmitSDCheck(const BasicBlock &BB) const { + return HasPrologue && !HasIRCheck && dyn_cast<ReturnInst>(BB.getTerminator()); +} diff --git a/gnu/llvm/lib/CodeGen/StatepointExampleGC.cpp b/gnu/llvm/lib/CodeGen/StatepointExampleGC.cpp deleted file mode 100644 index 3f60e18fafa..00000000000 --- a/gnu/llvm/lib/CodeGen/StatepointExampleGC.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//===-- StatepointDefaultGC.cpp - The default statepoint GC strategy ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains a GCStrategy which serves as an example for the usage -// of a statepoint based lowering strategy. This GCStrategy is intended to -// suitable as a default implementation usable with any collector which can -// consume the standard stackmap format generated by statepoints, uses the -// default addrespace to distinguish between gc managed and non-gc managed -// pointers, and has reasonable relocation semantics. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/GCStrategy.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Value.h" - -using namespace llvm; - -namespace { -class StatepointGC : public GCStrategy { -public: - StatepointGC() { - UseStatepoints = true; - // These options are all gc.root specific, we specify them so that the - // gc.root lowering code doesn't run. - InitRoots = false; - NeededSafePoints = 0; - UsesMetadata = false; - CustomRoots = false; - } - Optional<bool> isGCManagedPointer(const Type *Ty) const override { - // Method is only valid on pointer typed values. - const PointerType *PT = cast<PointerType>(Ty); - // For the sake of this example GC, we arbitrarily pick addrspace(1) as our - // GC managed heap. We know that a pointer into this heap needs to be - // updated and that no other pointer does. Note that addrspace(1) is used - // only as an example, it has no special meaning, and is not reserved for - // GC usage. - return (1 == PT->getAddressSpace()); - } -}; -} - -static GCRegistry::Add<StatepointGC> X("statepoint-example", - "an example strategy for statepoint"); - -namespace llvm { -void linkStatepointExampleGC() {} -} diff --git a/gnu/llvm/lib/CodeGen/TargetLoweringBase.cpp b/gnu/llvm/lib/CodeGen/TargetLoweringBase.cpp index 36a31c9d646..8ca2bf9e86d 100644 --- a/gnu/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/gnu/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -28,6 +28,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/Support/BranchProbability.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -43,6 +44,17 @@ static cl::opt<bool> JumpIsExpensiveOverride( cl::desc("Do not create extra branches to split comparison logic."), cl::Hidden); +// Although this default value is arbitrary, it is not random. It is assumed +// that a condition that evaluates the same way by a higher percentage than this +// is best represented as control flow. Therefore, the default value N should be +// set such that the win from N% correct executions is greater than the loss +// from (100 - N)% mispredicted executions for the majority of intended targets. +static cl::opt<int> MinPercentageForPredictableBranch( + "min-predictable-branch", cl::init(99), + cl::desc("Minimum percentage (0-100) that a condition must be either true " + "or false to assume that the condition is predictable"), + cl::Hidden); + /// InitLibcallNames - Set default libcall names. /// static void InitLibcallNames(const char **Names, const Triple &TT) { @@ -87,18 +99,6 @@ static void InitLibcallNames(const char **Names, const Triple &TT) { Names[RTLIB::UREM_I64] = "__umoddi3"; Names[RTLIB::UREM_I128] = "__umodti3"; - // These are generally not available. - Names[RTLIB::SDIVREM_I8] = nullptr; - Names[RTLIB::SDIVREM_I16] = nullptr; - Names[RTLIB::SDIVREM_I32] = nullptr; - Names[RTLIB::SDIVREM_I64] = nullptr; - Names[RTLIB::SDIVREM_I128] = nullptr; - Names[RTLIB::UDIVREM_I8] = nullptr; - Names[RTLIB::UDIVREM_I16] = nullptr; - Names[RTLIB::UDIVREM_I32] = nullptr; - Names[RTLIB::UDIVREM_I64] = nullptr; - Names[RTLIB::UDIVREM_I128] = nullptr; - Names[RTLIB::NEG_I32] = "__negsi2"; Names[RTLIB::NEG_I64] = "__negdi2"; Names[RTLIB::ADD_F32] = "__addsf3"; @@ -231,11 +231,21 @@ static void InitLibcallNames(const char **Names, const Triple &TT) { Names[RTLIB::COPYSIGN_F80] = "copysignl"; Names[RTLIB::COPYSIGN_F128] = "copysignl"; Names[RTLIB::COPYSIGN_PPCF128] = "copysignl"; + Names[RTLIB::FPEXT_F32_PPCF128] = "__gcc_stoq"; + Names[RTLIB::FPEXT_F64_PPCF128] = "__gcc_dtoq"; Names[RTLIB::FPEXT_F64_F128] = "__extenddftf2"; Names[RTLIB::FPEXT_F32_F128] = "__extendsftf2"; Names[RTLIB::FPEXT_F32_F64] = "__extendsfdf2"; - Names[RTLIB::FPEXT_F16_F32] = "__gnu_h2f_ieee"; - Names[RTLIB::FPROUND_F32_F16] = "__gnu_f2h_ieee"; + if (TT.isOSDarwin()) { + // For f16/f32 conversions, Darwin uses the standard naming scheme, instead + // of the gnueabi-style __gnu_*_ieee. + // FIXME: What about other targets? + Names[RTLIB::FPEXT_F16_F32] = "__extendhfsf2"; + Names[RTLIB::FPROUND_F32_F16] = "__truncsfhf2"; + } else { + Names[RTLIB::FPEXT_F16_F32] = "__gnu_h2f_ieee"; + Names[RTLIB::FPROUND_F32_F16] = "__gnu_f2h_ieee"; + } Names[RTLIB::FPROUND_F64_F16] = "__truncdfhf2"; Names[RTLIB::FPROUND_F80_F16] = "__truncxfhf2"; Names[RTLIB::FPROUND_F128_F16] = "__trunctfhf2"; @@ -243,10 +253,10 @@ static void InitLibcallNames(const char **Names, const Triple &TT) { Names[RTLIB::FPROUND_F64_F32] = "__truncdfsf2"; Names[RTLIB::FPROUND_F80_F32] = "__truncxfsf2"; Names[RTLIB::FPROUND_F128_F32] = "__trunctfsf2"; - Names[RTLIB::FPROUND_PPCF128_F32] = "__trunctfsf2"; + Names[RTLIB::FPROUND_PPCF128_F32] = "__gcc_qtos"; Names[RTLIB::FPROUND_F80_F64] = "__truncxfdf2"; Names[RTLIB::FPROUND_F128_F64] = "__trunctfdf2"; - Names[RTLIB::FPROUND_PPCF128_F64] = "__trunctfdf2"; + Names[RTLIB::FPROUND_PPCF128_F64] = "__gcc_qtod"; Names[RTLIB::FPTOSINT_F32_I32] = "__fixsfsi"; Names[RTLIB::FPTOSINT_F32_I64] = "__fixsfdi"; Names[RTLIB::FPTOSINT_F32_I128] = "__fixsfti"; @@ -259,7 +269,7 @@ static void InitLibcallNames(const char **Names, const Triple &TT) { Names[RTLIB::FPTOSINT_F128_I32] = "__fixtfsi"; Names[RTLIB::FPTOSINT_F128_I64] = "__fixtfdi"; Names[RTLIB::FPTOSINT_F128_I128] = "__fixtfti"; - Names[RTLIB::FPTOSINT_PPCF128_I32] = "__fixtfsi"; + Names[RTLIB::FPTOSINT_PPCF128_I32] = "__gcc_qtou"; Names[RTLIB::FPTOSINT_PPCF128_I64] = "__fixtfdi"; Names[RTLIB::FPTOSINT_PPCF128_I128] = "__fixtfti"; Names[RTLIB::FPTOUINT_F32_I32] = "__fixunssfsi"; @@ -281,7 +291,7 @@ static void InitLibcallNames(const char **Names, const Triple &TT) { Names[RTLIB::SINTTOFP_I32_F64] = "__floatsidf"; Names[RTLIB::SINTTOFP_I32_F80] = "__floatsixf"; Names[RTLIB::SINTTOFP_I32_F128] = "__floatsitf"; - Names[RTLIB::SINTTOFP_I32_PPCF128] = "__floatsitf"; + Names[RTLIB::SINTTOFP_I32_PPCF128] = "__gcc_itoq"; Names[RTLIB::SINTTOFP_I64_F32] = "__floatdisf"; Names[RTLIB::SINTTOFP_I64_F64] = "__floatdidf"; Names[RTLIB::SINTTOFP_I64_F80] = "__floatdixf"; @@ -296,7 +306,7 @@ static void InitLibcallNames(const char **Names, const Triple &TT) { Names[RTLIB::UINTTOFP_I32_F64] = "__floatunsidf"; Names[RTLIB::UINTTOFP_I32_F80] = "__floatunsixf"; Names[RTLIB::UINTTOFP_I32_F128] = "__floatunsitf"; - Names[RTLIB::UINTTOFP_I32_PPCF128] = "__floatunsitf"; + Names[RTLIB::UINTTOFP_I32_PPCF128] = "__gcc_utoq"; Names[RTLIB::UINTTOFP_I64_F32] = "__floatundisf"; Names[RTLIB::UINTTOFP_I64_F64] = "__floatundidf"; Names[RTLIB::UINTTOFP_I64_F80] = "__floatundixf"; @@ -310,27 +320,35 @@ static void InitLibcallNames(const char **Names, const Triple &TT) { Names[RTLIB::OEQ_F32] = "__eqsf2"; Names[RTLIB::OEQ_F64] = "__eqdf2"; Names[RTLIB::OEQ_F128] = "__eqtf2"; + Names[RTLIB::OEQ_PPCF128] = "__gcc_qeq"; Names[RTLIB::UNE_F32] = "__nesf2"; Names[RTLIB::UNE_F64] = "__nedf2"; Names[RTLIB::UNE_F128] = "__netf2"; + Names[RTLIB::UNE_PPCF128] = "__gcc_qne"; Names[RTLIB::OGE_F32] = "__gesf2"; Names[RTLIB::OGE_F64] = "__gedf2"; Names[RTLIB::OGE_F128] = "__getf2"; + Names[RTLIB::OGE_PPCF128] = "__gcc_qge"; Names[RTLIB::OLT_F32] = "__ltsf2"; Names[RTLIB::OLT_F64] = "__ltdf2"; Names[RTLIB::OLT_F128] = "__lttf2"; + Names[RTLIB::OLT_PPCF128] = "__gcc_qlt"; Names[RTLIB::OLE_F32] = "__lesf2"; Names[RTLIB::OLE_F64] = "__ledf2"; Names[RTLIB::OLE_F128] = "__letf2"; + Names[RTLIB::OLE_PPCF128] = "__gcc_qle"; Names[RTLIB::OGT_F32] = "__gtsf2"; Names[RTLIB::OGT_F64] = "__gtdf2"; Names[RTLIB::OGT_F128] = "__gttf2"; + Names[RTLIB::OGT_PPCF128] = "__gcc_qgt"; Names[RTLIB::UO_F32] = "__unordsf2"; Names[RTLIB::UO_F64] = "__unorddf2"; Names[RTLIB::UO_F128] = "__unordtf2"; + Names[RTLIB::UO_PPCF128] = "__gcc_qunord"; Names[RTLIB::O_F32] = "__unordsf2"; Names[RTLIB::O_F64] = "__unorddf2"; Names[RTLIB::O_F128] = "__unordtf2"; + Names[RTLIB::O_PPCF128] = "__gcc_qunord"; Names[RTLIB::MEMCPY] = "memcpy"; Names[RTLIB::MEMMOVE] = "memmove"; Names[RTLIB::MEMSET] = "memset"; @@ -395,36 +413,79 @@ static void InitLibcallNames(const char **Names, const Triple &TT) { Names[RTLIB::SYNC_FETCH_AND_UMIN_4] = "__sync_fetch_and_umin_4"; Names[RTLIB::SYNC_FETCH_AND_UMIN_8] = "__sync_fetch_and_umin_8"; Names[RTLIB::SYNC_FETCH_AND_UMIN_16] = "__sync_fetch_and_umin_16"; - - if (TT.getEnvironment() == Triple::GNU) { + + Names[RTLIB::ATOMIC_LOAD] = "__atomic_load"; + Names[RTLIB::ATOMIC_LOAD_1] = "__atomic_load_1"; + Names[RTLIB::ATOMIC_LOAD_2] = "__atomic_load_2"; + Names[RTLIB::ATOMIC_LOAD_4] = "__atomic_load_4"; + Names[RTLIB::ATOMIC_LOAD_8] = "__atomic_load_8"; + Names[RTLIB::ATOMIC_LOAD_16] = "__atomic_load_16"; + + Names[RTLIB::ATOMIC_STORE] = "__atomic_store"; + Names[RTLIB::ATOMIC_STORE_1] = "__atomic_store_1"; + Names[RTLIB::ATOMIC_STORE_2] = "__atomic_store_2"; + Names[RTLIB::ATOMIC_STORE_4] = "__atomic_store_4"; + Names[RTLIB::ATOMIC_STORE_8] = "__atomic_store_8"; + Names[RTLIB::ATOMIC_STORE_16] = "__atomic_store_16"; + + Names[RTLIB::ATOMIC_EXCHANGE] = "__atomic_exchange"; + Names[RTLIB::ATOMIC_EXCHANGE_1] = "__atomic_exchange_1"; + Names[RTLIB::ATOMIC_EXCHANGE_2] = "__atomic_exchange_2"; + Names[RTLIB::ATOMIC_EXCHANGE_4] = "__atomic_exchange_4"; + Names[RTLIB::ATOMIC_EXCHANGE_8] = "__atomic_exchange_8"; + Names[RTLIB::ATOMIC_EXCHANGE_16] = "__atomic_exchange_16"; + + Names[RTLIB::ATOMIC_COMPARE_EXCHANGE] = "__atomic_compare_exchange"; + Names[RTLIB::ATOMIC_COMPARE_EXCHANGE_1] = "__atomic_compare_exchange_1"; + Names[RTLIB::ATOMIC_COMPARE_EXCHANGE_2] = "__atomic_compare_exchange_2"; + Names[RTLIB::ATOMIC_COMPARE_EXCHANGE_4] = "__atomic_compare_exchange_4"; + Names[RTLIB::ATOMIC_COMPARE_EXCHANGE_8] = "__atomic_compare_exchange_8"; + Names[RTLIB::ATOMIC_COMPARE_EXCHANGE_16] = "__atomic_compare_exchange_16"; + + Names[RTLIB::ATOMIC_FETCH_ADD_1] = "__atomic_fetch_add_1"; + Names[RTLIB::ATOMIC_FETCH_ADD_2] = "__atomic_fetch_add_2"; + Names[RTLIB::ATOMIC_FETCH_ADD_4] = "__atomic_fetch_add_4"; + Names[RTLIB::ATOMIC_FETCH_ADD_8] = "__atomic_fetch_add_8"; + Names[RTLIB::ATOMIC_FETCH_ADD_16] = "__atomic_fetch_add_16"; + Names[RTLIB::ATOMIC_FETCH_SUB_1] = "__atomic_fetch_sub_1"; + Names[RTLIB::ATOMIC_FETCH_SUB_2] = "__atomic_fetch_sub_2"; + Names[RTLIB::ATOMIC_FETCH_SUB_4] = "__atomic_fetch_sub_4"; + Names[RTLIB::ATOMIC_FETCH_SUB_8] = "__atomic_fetch_sub_8"; + Names[RTLIB::ATOMIC_FETCH_SUB_16] = "__atomic_fetch_sub_16"; + Names[RTLIB::ATOMIC_FETCH_AND_1] = "__atomic_fetch_and_1"; + Names[RTLIB::ATOMIC_FETCH_AND_2] = "__atomic_fetch_and_2"; + Names[RTLIB::ATOMIC_FETCH_AND_4] = "__atomic_fetch_and_4"; + Names[RTLIB::ATOMIC_FETCH_AND_8] = "__atomic_fetch_and_8"; + Names[RTLIB::ATOMIC_FETCH_AND_16] = "__atomic_fetch_and_16"; + Names[RTLIB::ATOMIC_FETCH_OR_1] = "__atomic_fetch_or_1"; + Names[RTLIB::ATOMIC_FETCH_OR_2] = "__atomic_fetch_or_2"; + Names[RTLIB::ATOMIC_FETCH_OR_4] = "__atomic_fetch_or_4"; + Names[RTLIB::ATOMIC_FETCH_OR_8] = "__atomic_fetch_or_8"; + Names[RTLIB::ATOMIC_FETCH_OR_16] = "__atomic_fetch_or_16"; + Names[RTLIB::ATOMIC_FETCH_XOR_1] = "__atomic_fetch_xor_1"; + Names[RTLIB::ATOMIC_FETCH_XOR_2] = "__atomic_fetch_xor_2"; + Names[RTLIB::ATOMIC_FETCH_XOR_4] = "__atomic_fetch_xor_4"; + Names[RTLIB::ATOMIC_FETCH_XOR_8] = "__atomic_fetch_xor_8"; + Names[RTLIB::ATOMIC_FETCH_XOR_16] = "__atomic_fetch_xor_16"; + Names[RTLIB::ATOMIC_FETCH_NAND_1] = "__atomic_fetch_nand_1"; + Names[RTLIB::ATOMIC_FETCH_NAND_2] = "__atomic_fetch_nand_2"; + Names[RTLIB::ATOMIC_FETCH_NAND_4] = "__atomic_fetch_nand_4"; + Names[RTLIB::ATOMIC_FETCH_NAND_8] = "__atomic_fetch_nand_8"; + Names[RTLIB::ATOMIC_FETCH_NAND_16] = "__atomic_fetch_nand_16"; + + if (TT.isGNUEnvironment()) { Names[RTLIB::SINCOS_F32] = "sincosf"; Names[RTLIB::SINCOS_F64] = "sincos"; Names[RTLIB::SINCOS_F80] = "sincosl"; Names[RTLIB::SINCOS_F128] = "sincosl"; Names[RTLIB::SINCOS_PPCF128] = "sincosl"; - } else { - // These are generally not available. - Names[RTLIB::SINCOS_F32] = nullptr; - Names[RTLIB::SINCOS_F64] = nullptr; - Names[RTLIB::SINCOS_F80] = nullptr; - Names[RTLIB::SINCOS_F128] = nullptr; - Names[RTLIB::SINCOS_PPCF128] = nullptr; } if (!TT.isOSOpenBSD()) { Names[RTLIB::STACKPROTECTOR_CHECK_FAIL] = "__stack_chk_fail"; - } else { - // These are generally not available. - Names[RTLIB::STACKPROTECTOR_CHECK_FAIL] = nullptr; } - // For f16/f32 conversions, Darwin uses the standard naming scheme, instead - // of the gnueabi-style __gnu_*_ieee. - // FIXME: What about other targets? - if (TT.isOSDarwin()) { - Names[RTLIB::FPEXT_F16_F32] = "__extendhfsf2"; - Names[RTLIB::FPROUND_F32_F16] = "__truncsfhf2"; - } + Names[RTLIB::DEOPTIMIZE] = "__llvm_deoptimize"; } /// InitLibcallCallingConvs - Set default libcall CallingConvs. @@ -446,9 +507,13 @@ RTLIB::Libcall RTLIB::getFPEXT(EVT OpVT, EVT RetVT) { return FPEXT_F32_F64; if (RetVT == MVT::f128) return FPEXT_F32_F128; + if (RetVT == MVT::ppcf128) + return FPEXT_F32_PPCF128; } else if (OpVT == MVT::f64) { if (RetVT == MVT::f128) return FPEXT_F64_F128; + else if (RetVT == MVT::ppcf128) + return FPEXT_F64_PPCF128; } return UNKNOWN_LIBCALL; @@ -653,7 +718,7 @@ RTLIB::Libcall RTLIB::getUINTTOFP(EVT OpVT, EVT RetVT) { return UNKNOWN_LIBCALL; } -RTLIB::Libcall RTLIB::getATOMIC(unsigned Opc, MVT VT) { +RTLIB::Libcall RTLIB::getSYNC(unsigned Opc, MVT VT) { #define OP_TO_LIBCALL(Name, Enum) \ case Name: \ switch (VT.SimpleTy) { \ @@ -698,27 +763,35 @@ static void InitCmpLibcallCCs(ISD::CondCode *CCs) { CCs[RTLIB::OEQ_F32] = ISD::SETEQ; CCs[RTLIB::OEQ_F64] = ISD::SETEQ; CCs[RTLIB::OEQ_F128] = ISD::SETEQ; + CCs[RTLIB::OEQ_PPCF128] = ISD::SETEQ; CCs[RTLIB::UNE_F32] = ISD::SETNE; CCs[RTLIB::UNE_F64] = ISD::SETNE; CCs[RTLIB::UNE_F128] = ISD::SETNE; + CCs[RTLIB::UNE_PPCF128] = ISD::SETNE; CCs[RTLIB::OGE_F32] = ISD::SETGE; CCs[RTLIB::OGE_F64] = ISD::SETGE; CCs[RTLIB::OGE_F128] = ISD::SETGE; + CCs[RTLIB::OGE_PPCF128] = ISD::SETGE; CCs[RTLIB::OLT_F32] = ISD::SETLT; CCs[RTLIB::OLT_F64] = ISD::SETLT; CCs[RTLIB::OLT_F128] = ISD::SETLT; + CCs[RTLIB::OLT_PPCF128] = ISD::SETLT; CCs[RTLIB::OLE_F32] = ISD::SETLE; CCs[RTLIB::OLE_F64] = ISD::SETLE; CCs[RTLIB::OLE_F128] = ISD::SETLE; + CCs[RTLIB::OLE_PPCF128] = ISD::SETLE; CCs[RTLIB::OGT_F32] = ISD::SETGT; CCs[RTLIB::OGT_F64] = ISD::SETGT; CCs[RTLIB::OGT_F128] = ISD::SETGT; + CCs[RTLIB::OGT_PPCF128] = ISD::SETGT; CCs[RTLIB::UO_F32] = ISD::SETNE; CCs[RTLIB::UO_F64] = ISD::SETNE; CCs[RTLIB::UO_F128] = ISD::SETNE; + CCs[RTLIB::UO_PPCF128] = ISD::SETNE; CCs[RTLIB::O_F32] = ISD::SETEQ; CCs[RTLIB::O_F64] = ISD::SETEQ; CCs[RTLIB::O_F128] = ISD::SETEQ; + CCs[RTLIB::O_PPCF128] = ISD::SETEQ; } /// NOTE: The TargetMachine owns TLOF. @@ -752,8 +825,14 @@ TargetLoweringBase::TargetLoweringBase(const TargetMachine &tm) : TM(tm) { PrefLoopAlignment = 0; GatherAllAliasesMaxDepth = 6; MinStackArgumentAlignment = 1; - InsertFencesForAtomic = false; MinimumJumpTableEntries = 4; + // TODO: the default will be switched to 0 in the next commit, along + // with the Target-specific changes necessary. + MaxAtomicSizeInBitsSupported = 1024; + + MinCmpXchgSizeInBits = 0; + + std::fill(std::begin(LibcallRoutineNames), std::end(LibcallRoutineNames), nullptr); InitLibcallNames(LibcallRoutineNames, TM.getTargetTriple()); InitCmpLibcallCCs(CmpLibcallCCs); @@ -767,8 +846,9 @@ void TargetLoweringBase::initActions() { memset(TruncStoreActions, 0, sizeof(TruncStoreActions)); memset(IndexedModeActions, 0, sizeof(IndexedModeActions)); memset(CondCodeActions, 0, sizeof(CondCodeActions)); - memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*)); - memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray)); + std::fill(std::begin(RegClassForVT), std::end(RegClassForVT), nullptr); + std::fill(std::begin(TargetDAGCombineArray), + std::end(TargetDAGCombineArray), 0); // Set default actions for various operations. for (MVT VT : MVT::all_valuetypes()) { @@ -803,6 +883,10 @@ void TargetLoweringBase::initActions() { setOperationAction(ISD::SMULO, VT, Expand); setOperationAction(ISD::UMULO, VT, Expand); + // These default to Expand so they will be expanded to CTLZ/CTTZ by default. + setOperationAction(ISD::CTLZ_ZERO_UNDEF, VT, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, VT, Expand); + setOperationAction(ISD::BITREVERSE, VT, Expand); // These library functions default to expand. @@ -816,7 +900,7 @@ void TargetLoweringBase::initActions() { setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, VT, Expand); } - // For most targets @llvm.get.dynamic.area.offest just returns 0. + // For most targets @llvm.get.dynamic.area.offset just returns 0. setOperationAction(ISD::GET_DYNAMIC_AREA_OFFSET, VT, Expand); } @@ -843,8 +927,6 @@ void TargetLoweringBase::initActions() { setOperationAction(ISD::FEXP , VT, Expand); setOperationAction(ISD::FEXP2, VT, Expand); setOperationAction(ISD::FFLOOR, VT, Expand); - setOperationAction(ISD::FMINNUM, VT, Expand); - setOperationAction(ISD::FMAXNUM, VT, Expand); setOperationAction(ISD::FNEARBYINT, VT, Expand); setOperationAction(ISD::FCEIL, VT, Expand); setOperationAction(ISD::FRINT, VT, Expand); @@ -1090,9 +1172,10 @@ bool TargetLoweringBase::isLegalRC(const TargetRegisterClass *RC) const { /// Replace/modify any TargetFrameIndex operands with a targte-dependent /// sequence of memory operands that is recognized by PrologEpilogInserter. -MachineBasicBlock* -TargetLoweringBase::emitPatchPoint(MachineInstr *MI, +MachineBasicBlock * +TargetLoweringBase::emitPatchPoint(MachineInstr &InitialMI, MachineBasicBlock *MBB) const { + MachineInstr *MI = &InitialMI; MachineFunction &MF = *MI->getParent()->getParent(); MachineFrameInfo &MFI = *MF.getFrameInfo(); @@ -1151,7 +1234,7 @@ TargetLoweringBase::emitPatchPoint(MachineInstr *MI, // Add a new memory operand for this FI. assert(MFI.getObjectOffset(FI) != -1); - unsigned Flags = MachineMemOperand::MOLoad; + auto Flags = MachineMemOperand::MOLoad; if (MI->getOpcode() == TargetOpcode::STATEPOINT) { Flags |= MachineMemOperand::MOStore; Flags |= MachineMemOperand::MOVolatile; @@ -1250,10 +1333,17 @@ void TargetLoweringBase::computeRegisterProperties( // ppcf128 type is really two f64's. if (!isTypeLegal(MVT::ppcf128)) { - NumRegistersForVT[MVT::ppcf128] = 2*NumRegistersForVT[MVT::f64]; - RegisterTypeForVT[MVT::ppcf128] = MVT::f64; - TransformToType[MVT::ppcf128] = MVT::f64; - ValueTypeActions.setTypeAction(MVT::ppcf128, TypeExpandFloat); + if (isTypeLegal(MVT::f64)) { + NumRegistersForVT[MVT::ppcf128] = 2*NumRegistersForVT[MVT::f64]; + RegisterTypeForVT[MVT::ppcf128] = MVT::f64; + TransformToType[MVT::ppcf128] = MVT::f64; + ValueTypeActions.setTypeAction(MVT::ppcf128, TypeExpandFloat); + } else { + NumRegistersForVT[MVT::ppcf128] = NumRegistersForVT[MVT::i128]; + RegisterTypeForVT[MVT::ppcf128] = RegisterTypeForVT[MVT::i128]; + TransformToType[MVT::ppcf128] = MVT::i128; + ValueTypeActions.setTypeAction(MVT::ppcf128, TypeSoftenFloat); + } } // Decide how to handle f128. If the target does not have native f128 support, @@ -1308,13 +1398,12 @@ void TargetLoweringBase::computeRegisterProperties( case TypePromoteInteger: { // Try to promote the elements of integer vectors. If no legal // promotion was found, fall through to the widen-vector method. - for (unsigned nVT = i + 1; nVT <= MVT::LAST_VECTOR_VALUETYPE; ++nVT) { + for (unsigned nVT = i + 1; nVT <= MVT::LAST_INTEGER_VECTOR_VALUETYPE; ++nVT) { MVT SVT = (MVT::SimpleValueType) nVT; // Promote vectors of integers to vectors with the same number // of elements, with a wider element type. - if (SVT.getVectorElementType().getSizeInBits() > EltVT.getSizeInBits() - && SVT.getVectorNumElements() == NElts && isTypeLegal(SVT) - && SVT.getScalarType().isInteger()) { + if (SVT.getVectorElementType().getSizeInBits() > EltVT.getSizeInBits() && + SVT.getVectorNumElements() == NElts && isTypeLegal(SVT)) { TransformToType[i] = SVT; RegisterTypeForVT[i] = SVT; NumRegistersForVT[i] = 1; @@ -1553,6 +1642,9 @@ bool TargetLoweringBase::allowsMemoryAccess(LLVMContext &Context, return allowsMisalignedMemoryAccesses(VT, AddrSpace, Alignment, Fast); } +BranchProbability TargetLoweringBase::getPredictableBranchThreshold() const { + return BranchProbability(MinPercentageForPredictableBranch, 100); +} //===----------------------------------------------------------------------===// // TargetTransformInfo Helpers @@ -1715,3 +1807,34 @@ bool TargetLoweringBase::isLegalAddressingMode(const DataLayout &DL, return true; } + +//===----------------------------------------------------------------------===// +// Stack Protector +//===----------------------------------------------------------------------===// + +// For OpenBSD return its special guard variable. Otherwise return nullptr, +// so that SelectionDAG handle SSP. +Value *TargetLoweringBase::getIRStackGuard(IRBuilder<> &IRB) const { + if (getTargetMachine().getTargetTriple().isOSOpenBSD()) { + Module &M = *IRB.GetInsertBlock()->getParent()->getParent(); + PointerType *PtrTy = Type::getInt8PtrTy(M.getContext()); + return M.getOrInsertGlobal("__guard_local", PtrTy); + } + return nullptr; +} + +// Currently only support "standard" __stack_chk_guard. +// TODO: add LOAD_STACK_GUARD support. +void TargetLoweringBase::insertSSPDeclarations(Module &M) const { + M.getOrInsertGlobal("__stack_chk_guard", Type::getInt8PtrTy(M.getContext())); +} + +// Currently only support "standard" __stack_chk_guard. +// TODO: add LOAD_STACK_GUARD support. +Value *TargetLoweringBase::getSDagStackGuard(const Module &M) const { + return M.getGlobalVariable("__stack_chk_guard", true); +} + +Value *TargetLoweringBase::getSSPStackGuardCheck(const Module &M) const { + return nullptr; +} diff --git a/gnu/llvm/lib/CodeGen/module.modulemap b/gnu/llvm/lib/CodeGen/module.modulemap deleted file mode 100644 index d4f68bcc6ee..00000000000 --- a/gnu/llvm/lib/CodeGen/module.modulemap +++ /dev/null @@ -1 +0,0 @@ -module CodeGen { requires cplusplus umbrella "." module * { export * } } diff --git a/gnu/llvm/lib/DebugInfo/CodeView/Makefile b/gnu/llvm/lib/DebugInfo/CodeView/Makefile deleted file mode 100644 index 70e2bd01142..00000000000 --- a/gnu/llvm/lib/DebugInfo/CodeView/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/DebugInfo/CodeView/Makefile ---------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMDebugInfoCodeView -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/DebugInfo/DWARF/Makefile b/gnu/llvm/lib/DebugInfo/DWARF/Makefile deleted file mode 100644 index 863337353d0..00000000000 --- a/gnu/llvm/lib/DebugInfo/DWARF/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/DebugInfo/DWARF/Makefile ------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMDebugInfoDWARF -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/DebugInfo/DWARF/module.modulemap b/gnu/llvm/lib/DebugInfo/DWARF/module.modulemap deleted file mode 100644 index c2f624fd4b6..00000000000 --- a/gnu/llvm/lib/DebugInfo/DWARF/module.modulemap +++ /dev/null @@ -1 +0,0 @@ -module DebugInfoDWARF { requires cplusplus umbrella "." module * { export * } } diff --git a/gnu/llvm/lib/DebugInfo/Makefile b/gnu/llvm/lib/DebugInfo/Makefile deleted file mode 100644 index 6072af31441..00000000000 --- a/gnu/llvm/lib/DebugInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/DebugInfo/Makefile ------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../.. - -include $(LEVEL)/Makefile.config - -PARALLEL_DIRS := CodeView DWARF PDB Symbolize - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/DebugInfo/PDB/Makefile b/gnu/llvm/lib/DebugInfo/PDB/Makefile deleted file mode 100644 index 444019e5a18..00000000000 --- a/gnu/llvm/lib/DebugInfo/PDB/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/DebugInfo/PDB/Makefile --------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMDebugInfoPDB -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/DebugInfo/Symbolize/Makefile b/gnu/llvm/lib/DebugInfo/Symbolize/Makefile deleted file mode 100644 index 17aac939658..00000000000 --- a/gnu/llvm/lib/DebugInfo/Symbolize/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/DebugInfo/Symbolize/Makefile --------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMSymbolize -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/ExecutionEngine/IntelJITEvents/Makefile b/gnu/llvm/lib/ExecutionEngine/IntelJITEvents/Makefile deleted file mode 100644 index dcf3126cc52..00000000000 --- a/gnu/llvm/lib/ExecutionEngine/IntelJITEvents/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -##===- lib/ExecutionEngine/JITProfile/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../.. -LIBRARYNAME = LLVMIntelJITEvents - -include $(LEVEL)/Makefile.config - -SOURCES := IntelJITEventListener.cpp \ - jitprofiling.c -CPPFLAGS += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/gnu/llvm/lib/ExecutionEngine/Interpreter/Makefile b/gnu/llvm/lib/ExecutionEngine/Interpreter/Makefile deleted file mode 100644 index 5def1365c61..00000000000 --- a/gnu/llvm/lib/ExecutionEngine/Interpreter/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/ExecutionEngine/Interpreter/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMInterpreter - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/ExecutionEngine/MCJIT/Makefile b/gnu/llvm/lib/ExecutionEngine/MCJIT/Makefile deleted file mode 100644 index 967efbc0efa..00000000000 --- a/gnu/llvm/lib/ExecutionEngine/MCJIT/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/ExecutionEngine/MCJIT/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMMCJIT - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/ExecutionEngine/Makefile b/gnu/llvm/lib/ExecutionEngine/Makefile deleted file mode 100644 index e9a5b79ddf6..00000000000 --- a/gnu/llvm/lib/ExecutionEngine/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -##===- lib/ExecutionEngine/Makefile ------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../.. -LIBRARYNAME = LLVMExecutionEngine - -include $(LEVEL)/Makefile.config - -PARALLEL_DIRS = Interpreter MCJIT Orc RuntimeDyld - -ifeq ($(USE_INTEL_JITEVENTS), 1) -PARALLEL_DIRS += IntelJITEvents -endif - -ifeq ($(USE_OPROFILE), 1) -PARALLEL_DIRS += OProfileJIT -endif - -include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/gnu/llvm/lib/ExecutionEngine/OProfileJIT/Makefile b/gnu/llvm/lib/ExecutionEngine/OProfileJIT/Makefile deleted file mode 100644 index fd3adce26c1..00000000000 --- a/gnu/llvm/lib/ExecutionEngine/OProfileJIT/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -##===- lib/ExecutionEngine/OProfileJIT/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../.. -LIBRARYNAME = LLVMOProfileJIT - -include $(LEVEL)/Makefile.config - -SOURCES += OProfileJITEventListener.cpp \ - OProfileWrapper.cpp -CPPFLAGS += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/gnu/llvm/lib/ExecutionEngine/Orc/Makefile b/gnu/llvm/lib/ExecutionEngine/Orc/Makefile deleted file mode 100644 index ac302348ee7..00000000000 --- a/gnu/llvm/lib/ExecutionEngine/Orc/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/ExecutionEngine/OrcJIT/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMOrcJIT - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp b/gnu/llvm/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp deleted file mode 100644 index 01e829f7909..00000000000 --- a/gnu/llvm/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp +++ /dev/null @@ -1,171 +0,0 @@ -//===------ OrcArchSupport.cpp - Architecture specific support code -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/Triple.h" -#include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h" -#include "llvm/Support/Process.h" -#include <array> - -namespace llvm { -namespace orc { - -void OrcX86_64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, - void *CallbackMgr) { - - const uint8_t ResolverCode[] = { - // resolver_entry: - 0x55, // 0x00: pushq %rbp - 0x48, 0x89, 0xe5, // 0x01: movq %rsp, %rbp - 0x50, // 0x04: pushq %rax - 0x53, // 0x05: pushq %rbx - 0x51, // 0x06: pushq %rcx - 0x52, // 0x07: pushq %rdx - 0x56, // 0x08: pushq %rsi - 0x57, // 0x09: pushq %rdi - 0x41, 0x50, // 0x0a: pushq %r8 - 0x41, 0x51, // 0x0c: pushq %r9 - 0x41, 0x52, // 0x0e: pushq %r10 - 0x41, 0x53, // 0x10: pushq %r11 - 0x41, 0x54, // 0x12: pushq %r12 - 0x41, 0x55, // 0x14: pushq %r13 - 0x41, 0x56, // 0x16: pushq %r14 - 0x41, 0x57, // 0x18: pushq %r15 - 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00, // 0x1a: subq 20, %rsp - 0x48, 0x0f, 0xae, 0x04, 0x24, // 0x21: fxsave64 (%rsp) - 0x48, 0x8d, 0x3d, 0x43, 0x00, 0x00, 0x00, // 0x26: leaq 67(%rip), %rdi - 0x48, 0x8b, 0x3f, // 0x2d: movq (%rdi), %rdi - 0x48, 0x8b, 0x75, 0x08, // 0x30: movq 8(%rbp), %rsi - 0x48, 0x83, 0xee, 0x06, // 0x34: subq $6, %rsi - 0x48, 0xb8, // 0x38: movabsq $0, %rax - - // 0x3a: JIT re-entry fn addr: - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0xff, 0xd0, // 0x42: callq *%rax - 0x48, 0x89, 0x45, 0x08, // 0x44: movq %rax, 8(%rbp) - 0x48, 0x0f, 0xae, 0x0c, 0x24, // 0x48: fxrstor64 (%rsp) - 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00, // 0x4d: addq 20, %rsp - 0x41, 0x5f, // 0x54: popq %r15 - 0x41, 0x5e, // 0x56: popq %r14 - 0x41, 0x5d, // 0x58: popq %r13 - 0x41, 0x5c, // 0x5a: popq %r12 - 0x41, 0x5b, // 0x5c: popq %r11 - 0x41, 0x5a, // 0x5e: popq %r10 - 0x41, 0x59, // 0x60: popq %r9 - 0x41, 0x58, // 0x62: popq %r8 - 0x5f, // 0x64: popq %rdi - 0x5e, // 0x65: popq %rsi - 0x5a, // 0x66: popq %rdx - 0x59, // 0x67: popq %rcx - 0x5b, // 0x68: popq %rbx - 0x58, // 0x69: popq %rax - 0x5d, // 0x6a: popq %rbp - 0xc3, // 0x6b: retq - 0x00, 0x00, 0x00, 0x00, // 0x6c: <padding> - - // 0x70: Callback mgr address. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - const unsigned ReentryFnAddrOffset = 0x3a; - const unsigned CallbackMgrAddrOffset = 0x70; - - memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); - memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); - memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, - sizeof(CallbackMgr)); -} - -void OrcX86_64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, - unsigned NumTrampolines) { - - unsigned OffsetToPtr = NumTrampolines * TrampolineSize; - - memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr, sizeof(void*)); - - uint64_t *Trampolines = reinterpret_cast<uint64_t*>(TrampolineMem); - uint64_t CallIndirPCRel = 0xf1c40000000015ff; - - for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) - Trampolines[I] = CallIndirPCRel | ((OffsetToPtr - 6) << 16); -} - -std::error_code OrcX86_64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, - void *InitialPtrVal) { - // Stub format is: - // - // .section __orc_stubs - // stub1: - // jmpq *ptr1(%rip) - // .byte 0xC4 ; <- Invalid opcode padding. - // .byte 0xF1 - // stub2: - // jmpq *ptr2(%rip) - // - // ... - // - // .section __orc_ptrs - // ptr1: - // .quad 0x0 - // ptr2: - // .quad 0x0 - // - // ... - - const unsigned StubSize = IndirectStubsInfo::StubSize; - - // Emit at least MinStubs, rounded up to fill the pages allocated. - unsigned PageSize = sys::Process::getPageSize(); - unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; - unsigned NumStubs = (NumPages * PageSize) / StubSize; - - // Allocate memory for stubs and pointers in one call. - std::error_code EC; - auto StubsMem = - sys::OwningMemoryBlock( - sys::Memory::allocateMappedMemory(2 * NumPages * PageSize, nullptr, - sys::Memory::MF_READ | - sys::Memory::MF_WRITE, - EC)); - - if (EC) - return EC; - - // Create separate MemoryBlocks representing the stubs and pointers. - sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); - sys::MemoryBlock PtrsBlock(static_cast<char*>(StubsMem.base()) + - NumPages * PageSize, - NumPages * PageSize); - - // Populate the stubs page stubs and mark it executable. - uint64_t *Stub = reinterpret_cast<uint64_t*>(StubsBlock.base()); - uint64_t PtrOffsetField = - static_cast<uint64_t>(NumPages * PageSize - 6) << 16; - for (unsigned I = 0; I < NumStubs; ++I) - Stub[I] = 0xF1C40000000025ff | PtrOffsetField; - - if (auto EC = sys::Memory::protectMappedMemory(StubsBlock, - sys::Memory::MF_READ | - sys::Memory::MF_EXEC)) - return EC; - - // Initialize all pointers to point at FailureAddress. - void **Ptr = reinterpret_cast<void**>(PtrsBlock.base()); - for (unsigned I = 0; I < NumStubs; ++I) - Ptr[I] = InitialPtrVal; - - StubsInfo.NumStubs = NumStubs; - StubsInfo.StubsMem = std::move(StubsMem); - - return std::error_code(); -} - -} // End namespace orc. -} // End namespace llvm. diff --git a/gnu/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp b/gnu/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp deleted file mode 100644 index 956daae372d..00000000000 --- a/gnu/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===-------- OrcCBindingsStack.cpp - Orc JIT stack for C bindings --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "OrcCBindingsStack.h" - -#include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/DynamicLibrary.h" -#include <cstdio> -#include <system_error> - -using namespace llvm; - -std::unique_ptr<OrcCBindingsStack::CompileCallbackMgr> -OrcCBindingsStack::createCompileCallbackMgr(Triple T) { - switch (T.getArch()) { - default: return nullptr; - - case Triple::x86_64: { - typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64> CCMgrT; - return llvm::make_unique<CCMgrT>(0); - } - } -} - -OrcCBindingsStack::IndirectStubsManagerBuilder -OrcCBindingsStack::createIndirectStubsMgrBuilder(Triple T) { - switch (T.getArch()) { - default: return nullptr; - - case Triple::x86_64: - return [](){ - return llvm::make_unique< - orc::LocalIndirectStubsManager<orc::OrcX86_64>>(); - }; - } -} diff --git a/gnu/llvm/lib/ExecutionEngine/RuntimeDyld/Makefile b/gnu/llvm/lib/ExecutionEngine/RuntimeDyld/Makefile deleted file mode 100644 index 5d6f26d950f..00000000000 --- a/gnu/llvm/lib/ExecutionEngine/RuntimeDyld/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/ExecutionEngine/MCJIT/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMRuntimeDyld - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Fuzzer/FuzzerInterface.cpp b/gnu/llvm/lib/Fuzzer/FuzzerInterface.cpp deleted file mode 100644 index bcd726fc08e..00000000000 --- a/gnu/llvm/lib/Fuzzer/FuzzerInterface.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//===- FuzzerInterface.cpp - Mutate a test input --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Parts of public interface for libFuzzer. -//===----------------------------------------------------------------------===// - - -#include "FuzzerInterface.h" -#include "FuzzerInternal.h" - -namespace fuzzer { - -void FuzzerRandomLibc::ResetSeed(unsigned int seed) { srand(seed); } - -size_t FuzzerRandomLibc::Rand() { return rand(); } - -UserSuppliedFuzzer::UserSuppliedFuzzer(FuzzerRandomBase *Rand) - : Rand(Rand), MD(*Rand) {} - -UserSuppliedFuzzer::~UserSuppliedFuzzer() { - if (OwnRand) - delete Rand; -} - -} // namespace fuzzer. diff --git a/gnu/llvm/lib/Fuzzer/FuzzerSanitizerOptions.cpp b/gnu/llvm/lib/Fuzzer/FuzzerSanitizerOptions.cpp deleted file mode 100644 index b2f20dd4ddf..00000000000 --- a/gnu/llvm/lib/Fuzzer/FuzzerSanitizerOptions.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//===- FuzzerSanitizerOptions.cpp - default flags for sanitizers ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Set default options for sanitizers while running the fuzzer. -// Options reside in a separate file, so if we don't want to set the default -// options we simply do not link this file in. -// ASAN options: -// * don't dump the coverage to disk. -// * enable coverage by default. -// * enable handle_abort. -//===----------------------------------------------------------------------===// -extern "C" const char *__asan_default_options() { - return "coverage_pcs=0:coverage=1:handle_abort=1"; -} diff --git a/gnu/llvm/lib/Fuzzer/pull_and_push_fuzz_corpus.sh b/gnu/llvm/lib/Fuzzer/pull_and_push_fuzz_corpus.sh deleted file mode 100755 index 05c322c6e5b..00000000000 --- a/gnu/llvm/lib/Fuzzer/pull_and_push_fuzz_corpus.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# A simple script to synchronise a fuzz test corpus -# with an external git repository. -# Usage: -# pull_and_push_fuzz_corpus.sh DIR -# It assumes that DIR is inside a git repo and push -# can be done w/o typing a password. -cd $1 -git add * -git commit -m "fuzz test corpus" -git pull --rebase --no-edit -for((attempt=0; attempt<5; attempt++)); do - echo GIT PUSH $1 ATTEMPT $attempt - if $(git push); then break; fi - git pull --rebase --no-edit -done - diff --git a/gnu/llvm/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp b/gnu/llvm/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp deleted file mode 100644 index 59f83b57bfa..00000000000 --- a/gnu/llvm/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Simple test for a fuzzer. -// The fuzzer must find the string "Hi!" preceded by a magic value. -// Uses UserSuppliedFuzzer which ensures that the magic is present. -#include <cstdint> -#include <cassert> -#include <cstdlib> -#include <cstddef> -#include <cstring> -#include <iostream> - -#include "FuzzerInterface.h" - -static const uint64_t kMagic = 8860221463604ULL; - -class MyFuzzer : public fuzzer::UserSuppliedFuzzer { - public: - MyFuzzer(fuzzer::FuzzerRandomBase *Rand) - : fuzzer::UserSuppliedFuzzer(Rand) {} - int TargetFunction(const uint8_t *Data, size_t Size) { - if (Size <= 10) return 0; - if (memcmp(Data, &kMagic, sizeof(kMagic))) return 0; - // It's hard to get here w/o advanced fuzzing techniques (e.g. cmp tracing). - // So, we simply 'fix' the data in the custom mutator. - if (Data[8] == 'H') { - if (Data[9] == 'i') { - if (Data[10] == '!') { - std::cout << "BINGO; Found the target, exiting\n"; - exit(1); - } - } - } - return 0; - } - // Custom mutator. - virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { - assert(MaxSize > sizeof(kMagic)); - if (Size < sizeof(kMagic)) - Size = sizeof(kMagic); - // "Fix" the data, then mutate. - memcpy(Data, &kMagic, std::min(MaxSize, sizeof(kMagic))); - return fuzzer::UserSuppliedFuzzer::Mutate( - Data + sizeof(kMagic), Size - sizeof(kMagic), MaxSize - sizeof(kMagic)); - } - // No need to redefine CrossOver() here. -}; - -int main(int argc, char **argv) { - fuzzer::FuzzerRandomLibc Rand(0); - MyFuzzer F(&Rand); - fuzzer::FuzzerDriver(argc, argv, F); -} diff --git a/gnu/llvm/lib/IR/FunctionInfo.cpp b/gnu/llvm/lib/IR/FunctionInfo.cpp deleted file mode 100644 index 17a67bcf047..00000000000 --- a/gnu/llvm/lib/IR/FunctionInfo.cpp +++ /dev/null @@ -1,67 +0,0 @@ -//===-- FunctionInfo.cpp - Function Info Index ----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the function info index and summary classes for the -// IR library. -// -//===----------------------------------------------------------------------===// - -#include "llvm/IR/FunctionInfo.h" -#include "llvm/ADT/StringMap.h" -using namespace llvm; - -// Create the combined function index/summary from multiple -// per-module instances. -void FunctionInfoIndex::mergeFrom(std::unique_ptr<FunctionInfoIndex> Other, - uint64_t NextModuleId) { - - StringRef ModPath; - for (auto &OtherFuncInfoLists : *Other) { - std::string FuncName = OtherFuncInfoLists.getKey(); - FunctionInfoList &List = OtherFuncInfoLists.second; - - // Assert that the func info list only has one entry, since we shouldn't - // have duplicate names within a single per-module index. - assert(List.size() == 1); - std::unique_ptr<FunctionInfo> Info = std::move(List.front()); - - // Skip if there was no function summary section. - if (!Info->functionSummary()) - continue; - - // Add the module path string ref for this module if we haven't already - // saved a reference to it. - if (ModPath.empty()) - ModPath = - addModulePath(Info->functionSummary()->modulePath(), NextModuleId); - else - assert(ModPath == Info->functionSummary()->modulePath() && - "Each module in the combined map should have a unique ID"); - - // Note the module path string ref was copied above and is still owned by - // the original per-module index. Reset it to the new module path - // string reference owned by the combined index. - Info->functionSummary()->setModulePath(ModPath); - - // If it is a local function, rename it. - if (Info->functionSummary()->isLocalFunction()) { - // Any local functions are virtually renamed when being added to the - // combined index map, to disambiguate from other functions with - // the same name. The symbol table created for the combined index - // file should contain the renamed symbols. - FuncName = - FunctionInfoIndex::getGlobalNameForLocal(FuncName, NextModuleId); - } - - // Add new function info to existing list. There may be duplicates when - // combining FunctionMap entries, due to COMDAT functions. Any local - // functions were virtually renamed above. - addFunctionInfo(FuncName, std::move(Info)); - } -} diff --git a/gnu/llvm/lib/IR/Makefile b/gnu/llvm/lib/IR/Makefile deleted file mode 100644 index 329cd6636e9..00000000000 --- a/gnu/llvm/lib/IR/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -##===- lib/IR/Makefile -------------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../.. -LIBRARYNAME = LLVMCore -BUILD_ARCHIVE = 1 - -BUILT_SOURCES = $(PROJ_OBJ_ROOT)/include/llvm/IR/Intrinsics.gen \ - $(PROJ_OBJ_ROOT)/include/llvm/IR/Attributes.inc \ - $(PROJ_OBJ_ROOT)/lib/IR/AttributesCompatFunc.inc - -include $(LEVEL)/Makefile.common - -GENFILE:=$(PROJ_OBJ_ROOT)/include/llvm/IR/Intrinsics.gen -ATTRINCFILE:=$(PROJ_OBJ_ROOT)/include/llvm/IR/Attributes.inc -ATTRCOMPATFUNCINCFILE:=$(PROJ_OBJ_ROOT)/lib/IR/AttributesCompatFunc.inc - -INTRINSICTD := $(PROJ_SRC_ROOT)/include/llvm/IR/Intrinsics.td -INTRINSICTDS := $(wildcard $(PROJ_SRC_ROOT)/include/llvm/IR/Intrinsics*.td) -ATTRIBUTESTD := $(PROJ_SRC_ROOT)/include/llvm/IR/Attributes.td -ATTRCOMPATFUNCTD := $(PROJ_SRC_ROOT)/lib/IR/AttributesCompatFunc.td - -$(ObjDir)/Intrinsics.gen.tmp: $(ObjDir)/.dir $(INTRINSICTDS) $(LLVM_TBLGEN) - $(Echo) Building Intrinsics.gen.tmp from Intrinsics.td - $(Verb) $(LLVMTableGen) $(call SYSPATH, $(INTRINSICTD)) -o $(call SYSPATH, $@) -gen-intrinsic - -$(GENFILE): $(ObjDir)/Intrinsics.gen.tmp $(PROJ_OBJ_ROOT)/include/llvm/IR/.dir - $(Verb) $(CMP) -s $@ $< || ( $(CP) $< $@ && \ - $(EchoCmd) Updated Intrinsics.gen because Intrinsics.gen.tmp \ - changed significantly. ) - -$(ObjDir)/Attributes.inc.tmp: $(ObjDir)/.dir $(ATTRIBUTESTD) $(LLVM_TBLGEN) - $(Echo) Building Attributes.inc.tmp from $(ATTRIBUTESTD) - $(Verb) $(LLVMTableGen) $(call SYSPATH, $(ATTRIBUTESTD)) -o $(call SYSPATH, $@) -gen-attrs - -$(ATTRINCFILE): $(ObjDir)/Attributes.inc.tmp $(PROJ_OBJ_ROOT)/include/llvm/IR/.dir - $(Verb) $(CMP) -s $@ $< || ( $(CP) $< $@ && \ - $(EchoCmd) Updated Attributes.inc because Attributes.inc.tmp \ - changed significantly. ) - -$(ObjDir)/AttributesCompatFunc.inc.tmp: $(ObjDir)/.dir $(ATTRCOMPATFUNCTD) $(LLVM_TBLGEN) - $(Echo) Building AttributesCompatFunc.inc.tmp from $(ATTRCOMPATFUNCTD) - $(Verb) $(LLVMTableGen) $(call SYSPATH, $(ATTRCOMPATFUNCTD)) -o $(call SYSPATH, $@) -gen-attrs - -$(ATTRCOMPATFUNCINCFILE): $(ObjDir)/AttributesCompatFunc.inc.tmp $(PROJ_OBJ_ROOT)/include/llvm/IR/.dir - $(Verb) $(CMP) -s $@ $< || ( $(CP) $< $@ && \ - $(EchoCmd) Updated AttributesCompatFunc.inc because AttributesCompatFunc.inc.tmp \ - changed significantly. ) - -install-local:: $(GENFILE) - $(Echo) Installing $(DESTDIR)$(PROJ_includedir)/llvm/IR/Intrinsics.gen - $(Verb) $(DataInstall) $(GENFILE) $(DESTDIR)$(PROJ_includedir)/llvm/IR/Intrinsics.gen - -install-local:: $(ATTRINCFILE) - $(Echo) Installing $(DESTDIR)$(PROJ_includedir)/llvm/IR/Attributes.inc - $(Verb) $(DataInstall) $(ATTRINCFILE) $(DESTDIR)$(PROJ_includedir)/llvm/IR/Attributes.inc diff --git a/gnu/llvm/lib/IR/module.modulemap b/gnu/llvm/lib/IR/module.modulemap deleted file mode 100644 index 9698e917834..00000000000 --- a/gnu/llvm/lib/IR/module.modulemap +++ /dev/null @@ -1 +0,0 @@ -module IR { requires cplusplus umbrella "." module * { export * } } diff --git a/gnu/llvm/lib/IRReader/Makefile b/gnu/llvm/lib/IRReader/Makefile deleted file mode 100644 index cf6bc113542..00000000000 --- a/gnu/llvm/lib/IRReader/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/IRReader/Makefile -------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME := LLVMIRReader -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/LTO/Makefile b/gnu/llvm/lib/LTO/Makefile deleted file mode 100644 index 55e2a5ef803..00000000000 --- a/gnu/llvm/lib/LTO/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/LTO/Makefile ------------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMLTO -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/LibDriver/Makefile b/gnu/llvm/lib/LibDriver/Makefile deleted file mode 100644 index 1c62eac9093..00000000000 --- a/gnu/llvm/lib/LibDriver/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -##===- lib/LibDriver/Makefile ------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMLibDriver -BUILD_ARCHIVE := 1 -BUILT_SOURCES = Options.inc -TABLEGEN_INC_FILES_COMMON = 1 - -include $(LEVEL)/Makefile.common - -$(ObjDir)/Options.inc.tmp : Options.td $(LLVM_TBLGEN) $(ObjDir)/.dir - $(Echo) "Building lib Driver Option tables with tblgen" - $(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< diff --git a/gnu/llvm/lib/LineEditor/Makefile b/gnu/llvm/lib/LineEditor/Makefile deleted file mode 100644 index c7ff6d8eaae..00000000000 --- a/gnu/llvm/lib/LineEditor/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/LineEditor/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMLineEditor -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Linker/Makefile b/gnu/llvm/lib/Linker/Makefile deleted file mode 100644 index 19e646b7483..00000000000 --- a/gnu/llvm/lib/Linker/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Linker/Makefile ---------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMLinker -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/MC/MCCodeGenInfo.cpp b/gnu/llvm/lib/MC/MCCodeGenInfo.cpp deleted file mode 100644 index 347ec2cd01e..00000000000 --- a/gnu/llvm/lib/MC/MCCodeGenInfo.cpp +++ /dev/null @@ -1,23 +0,0 @@ -//===-- MCCodeGenInfo.cpp - Target CodeGen Info -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file tracks information about the target which can affect codegen, -// asm parsing, and asm printing. For example, relocation model. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCCodeGenInfo.h" -using namespace llvm; - -void MCCodeGenInfo::initMCCodeGenInfo(Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL) { - RelocationModel = RM; - CMModel = CM; - OptLevel = OL; -} diff --git a/gnu/llvm/lib/MC/MCDisassembler/Makefile b/gnu/llvm/lib/MC/MCDisassembler/Makefile deleted file mode 100644 index 7d71cd381a7..00000000000 --- a/gnu/llvm/lib/MC/MCDisassembler/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/MC/MCDisassembler/Makefile ----------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMMCDisassembler - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/MC/MCParser/Makefile b/gnu/llvm/lib/MC/MCParser/Makefile deleted file mode 100644 index 4477757657c..00000000000 --- a/gnu/llvm/lib/MC/MCParser/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/MC/MCParser/Makefile ----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMMCParser -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/MC/MCSymbolizer.cpp b/gnu/llvm/lib/MC/MCSymbolizer.cpp deleted file mode 100644 index 4080e40b3f1..00000000000 --- a/gnu/llvm/lib/MC/MCSymbolizer.cpp +++ /dev/null @@ -1,15 +0,0 @@ -//===-- llvm/MC/MCSymbolizer.cpp - MCSymbolizer class -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSymbolizer.h" - -using namespace llvm; - -MCSymbolizer::~MCSymbolizer() { -} diff --git a/gnu/llvm/lib/MC/Makefile b/gnu/llvm/lib/MC/Makefile deleted file mode 100644 index bf8b7c0e783..00000000000 --- a/gnu/llvm/lib/MC/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/MC/Makefile -------------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMMC -BUILD_ARCHIVE := 1 -PARALLEL_DIRS := MCParser MCDisassembler - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/MC/YAML.cpp b/gnu/llvm/lib/MC/YAML.cpp deleted file mode 100644 index 067e91a26d3..00000000000 --- a/gnu/llvm/lib/MC/YAML.cpp +++ /dev/null @@ -1,65 +0,0 @@ -//===- YAML.cpp - YAMLIO utilities for object files -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines utility classes for handling the YAML representation of -// object files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/YAML.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <cctype> - -using namespace llvm; - -void yaml::ScalarTraits<yaml::BinaryRef>::output( - const yaml::BinaryRef &Val, void *, llvm::raw_ostream &Out) { - Val.writeAsHex(Out); -} - -StringRef yaml::ScalarTraits<yaml::BinaryRef>::input(StringRef Scalar, void *, - yaml::BinaryRef &Val) { - if (Scalar.size() % 2 != 0) - return "BinaryRef hex string must contain an even number of nybbles."; - // TODO: Can we improve YAMLIO to permit a more accurate diagnostic here? - // (e.g. a caret pointing to the offending character). - for (unsigned I = 0, N = Scalar.size(); I != N; ++I) - if (!isxdigit(Scalar[I])) - return "BinaryRef hex string must contain only hex digits."; - Val = yaml::BinaryRef(Scalar); - return StringRef(); -} - -void yaml::BinaryRef::writeAsBinary(raw_ostream &OS) const { - if (!DataIsHexString) { - OS.write((const char *)Data.data(), Data.size()); - return; - } - for (unsigned I = 0, N = Data.size(); I != N; I += 2) { - uint8_t Byte; - StringRef((const char *)&Data[I], 2).getAsInteger(16, Byte); - OS.write(Byte); - } -} - -void yaml::BinaryRef::writeAsHex(raw_ostream &OS) const { - if (binary_size() == 0) - return; - if (DataIsHexString) { - OS.write((const char *)Data.data(), Data.size()); - return; - } - for (ArrayRef<uint8_t>::iterator I = Data.begin(), E = Data.end(); I != E; - ++I) { - uint8_t Byte = *I; - OS << hexdigit(Byte >> 4); - OS << hexdigit(Byte & 0xf); - } -} diff --git a/gnu/llvm/lib/Makefile b/gnu/llvm/lib/Makefile deleted file mode 100644 index 9b76126b80a..00000000000 --- a/gnu/llvm/lib/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -##===- lib/Makefile ----------------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = .. - -include $(LEVEL)/Makefile.config - -PARALLEL_DIRS := IR AsmParser Bitcode Analysis Transforms CodeGen Target \ - ExecutionEngine Linker LTO MC Object Option DebugInfo \ - IRReader LineEditor ProfileData Passes LibDriver - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Object/COFFYAML.cpp b/gnu/llvm/lib/Object/COFFYAML.cpp deleted file mode 100644 index 4c1fca19bf1..00000000000 --- a/gnu/llvm/lib/Object/COFFYAML.cpp +++ /dev/null @@ -1,503 +0,0 @@ -//===- COFFYAML.cpp - COFF YAMLIO implementation --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines classes for handling the YAML representation of COFF. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Object/COFFYAML.h" - -#define ECase(X) IO.enumCase(Value, #X, COFF::X); -namespace llvm { - -namespace COFFYAML { -Section::Section() { memset(&Header, 0, sizeof(COFF::section)); } -Symbol::Symbol() { memset(&Header, 0, sizeof(COFF::symbol)); } -Object::Object() { memset(&Header, 0, sizeof(COFF::header)); } -} - -namespace yaml { -void ScalarEnumerationTraits<COFFYAML::COMDATType>::enumeration( - IO &IO, COFFYAML::COMDATType &Value) { - IO.enumCase(Value, "0", 0); - ECase(IMAGE_COMDAT_SELECT_NODUPLICATES); - ECase(IMAGE_COMDAT_SELECT_ANY); - ECase(IMAGE_COMDAT_SELECT_SAME_SIZE); - ECase(IMAGE_COMDAT_SELECT_EXACT_MATCH); - ECase(IMAGE_COMDAT_SELECT_ASSOCIATIVE); - ECase(IMAGE_COMDAT_SELECT_LARGEST); - ECase(IMAGE_COMDAT_SELECT_NEWEST); -} - -void -ScalarEnumerationTraits<COFFYAML::WeakExternalCharacteristics>::enumeration( - IO &IO, COFFYAML::WeakExternalCharacteristics &Value) { - IO.enumCase(Value, "0", 0); - ECase(IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY); - ECase(IMAGE_WEAK_EXTERN_SEARCH_LIBRARY); - ECase(IMAGE_WEAK_EXTERN_SEARCH_ALIAS); -} - -void ScalarEnumerationTraits<COFFYAML::AuxSymbolType>::enumeration( - IO &IO, COFFYAML::AuxSymbolType &Value) { - ECase(IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF); -} - -void ScalarEnumerationTraits<COFF::MachineTypes>::enumeration( - IO &IO, COFF::MachineTypes &Value) { - ECase(IMAGE_FILE_MACHINE_UNKNOWN); - ECase(IMAGE_FILE_MACHINE_AM33); - ECase(IMAGE_FILE_MACHINE_AMD64); - ECase(IMAGE_FILE_MACHINE_ARM); - ECase(IMAGE_FILE_MACHINE_ARMNT); - ECase(IMAGE_FILE_MACHINE_ARM64); - ECase(IMAGE_FILE_MACHINE_EBC); - ECase(IMAGE_FILE_MACHINE_I386); - ECase(IMAGE_FILE_MACHINE_IA64); - ECase(IMAGE_FILE_MACHINE_M32R); - ECase(IMAGE_FILE_MACHINE_MIPS16); - ECase(IMAGE_FILE_MACHINE_MIPSFPU); - ECase(IMAGE_FILE_MACHINE_MIPSFPU16); - ECase(IMAGE_FILE_MACHINE_POWERPC); - ECase(IMAGE_FILE_MACHINE_POWERPCFP); - ECase(IMAGE_FILE_MACHINE_R4000); - ECase(IMAGE_FILE_MACHINE_SH3); - ECase(IMAGE_FILE_MACHINE_SH3DSP); - ECase(IMAGE_FILE_MACHINE_SH4); - ECase(IMAGE_FILE_MACHINE_SH5); - ECase(IMAGE_FILE_MACHINE_THUMB); - ECase(IMAGE_FILE_MACHINE_WCEMIPSV2); -} - -void ScalarEnumerationTraits<COFF::SymbolBaseType>::enumeration( - IO &IO, COFF::SymbolBaseType &Value) { - ECase(IMAGE_SYM_TYPE_NULL); - ECase(IMAGE_SYM_TYPE_VOID); - ECase(IMAGE_SYM_TYPE_CHAR); - ECase(IMAGE_SYM_TYPE_SHORT); - ECase(IMAGE_SYM_TYPE_INT); - ECase(IMAGE_SYM_TYPE_LONG); - ECase(IMAGE_SYM_TYPE_FLOAT); - ECase(IMAGE_SYM_TYPE_DOUBLE); - ECase(IMAGE_SYM_TYPE_STRUCT); - ECase(IMAGE_SYM_TYPE_UNION); - ECase(IMAGE_SYM_TYPE_ENUM); - ECase(IMAGE_SYM_TYPE_MOE); - ECase(IMAGE_SYM_TYPE_BYTE); - ECase(IMAGE_SYM_TYPE_WORD); - ECase(IMAGE_SYM_TYPE_UINT); - ECase(IMAGE_SYM_TYPE_DWORD); -} - -void ScalarEnumerationTraits<COFF::SymbolStorageClass>::enumeration( - IO &IO, COFF::SymbolStorageClass &Value) { - ECase(IMAGE_SYM_CLASS_END_OF_FUNCTION); - ECase(IMAGE_SYM_CLASS_NULL); - ECase(IMAGE_SYM_CLASS_AUTOMATIC); - ECase(IMAGE_SYM_CLASS_EXTERNAL); - ECase(IMAGE_SYM_CLASS_STATIC); - ECase(IMAGE_SYM_CLASS_REGISTER); - ECase(IMAGE_SYM_CLASS_EXTERNAL_DEF); - ECase(IMAGE_SYM_CLASS_LABEL); - ECase(IMAGE_SYM_CLASS_UNDEFINED_LABEL); - ECase(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT); - ECase(IMAGE_SYM_CLASS_ARGUMENT); - ECase(IMAGE_SYM_CLASS_STRUCT_TAG); - ECase(IMAGE_SYM_CLASS_MEMBER_OF_UNION); - ECase(IMAGE_SYM_CLASS_UNION_TAG); - ECase(IMAGE_SYM_CLASS_TYPE_DEFINITION); - ECase(IMAGE_SYM_CLASS_UNDEFINED_STATIC); - ECase(IMAGE_SYM_CLASS_ENUM_TAG); - ECase(IMAGE_SYM_CLASS_MEMBER_OF_ENUM); - ECase(IMAGE_SYM_CLASS_REGISTER_PARAM); - ECase(IMAGE_SYM_CLASS_BIT_FIELD); - ECase(IMAGE_SYM_CLASS_BLOCK); - ECase(IMAGE_SYM_CLASS_FUNCTION); - ECase(IMAGE_SYM_CLASS_END_OF_STRUCT); - ECase(IMAGE_SYM_CLASS_FILE); - ECase(IMAGE_SYM_CLASS_SECTION); - ECase(IMAGE_SYM_CLASS_WEAK_EXTERNAL); - ECase(IMAGE_SYM_CLASS_CLR_TOKEN); -} - -void ScalarEnumerationTraits<COFF::SymbolComplexType>::enumeration( - IO &IO, COFF::SymbolComplexType &Value) { - ECase(IMAGE_SYM_DTYPE_NULL); - ECase(IMAGE_SYM_DTYPE_POINTER); - ECase(IMAGE_SYM_DTYPE_FUNCTION); - ECase(IMAGE_SYM_DTYPE_ARRAY); -} - -void ScalarEnumerationTraits<COFF::RelocationTypeI386>::enumeration( - IO &IO, COFF::RelocationTypeI386 &Value) { - ECase(IMAGE_REL_I386_ABSOLUTE); - ECase(IMAGE_REL_I386_DIR16); - ECase(IMAGE_REL_I386_REL16); - ECase(IMAGE_REL_I386_DIR32); - ECase(IMAGE_REL_I386_DIR32NB); - ECase(IMAGE_REL_I386_SEG12); - ECase(IMAGE_REL_I386_SECTION); - ECase(IMAGE_REL_I386_SECREL); - ECase(IMAGE_REL_I386_TOKEN); - ECase(IMAGE_REL_I386_SECREL7); - ECase(IMAGE_REL_I386_REL32); -} - -void ScalarEnumerationTraits<COFF::RelocationTypeAMD64>::enumeration( - IO &IO, COFF::RelocationTypeAMD64 &Value) { - ECase(IMAGE_REL_AMD64_ABSOLUTE); - ECase(IMAGE_REL_AMD64_ADDR64); - ECase(IMAGE_REL_AMD64_ADDR32); - ECase(IMAGE_REL_AMD64_ADDR32NB); - ECase(IMAGE_REL_AMD64_REL32); - ECase(IMAGE_REL_AMD64_REL32_1); - ECase(IMAGE_REL_AMD64_REL32_2); - ECase(IMAGE_REL_AMD64_REL32_3); - ECase(IMAGE_REL_AMD64_REL32_4); - ECase(IMAGE_REL_AMD64_REL32_5); - ECase(IMAGE_REL_AMD64_SECTION); - ECase(IMAGE_REL_AMD64_SECREL); - ECase(IMAGE_REL_AMD64_SECREL7); - ECase(IMAGE_REL_AMD64_TOKEN); - ECase(IMAGE_REL_AMD64_SREL32); - ECase(IMAGE_REL_AMD64_PAIR); - ECase(IMAGE_REL_AMD64_SSPAN32); -} - -void ScalarEnumerationTraits<COFF::WindowsSubsystem>::enumeration( - IO &IO, COFF::WindowsSubsystem &Value) { - ECase(IMAGE_SUBSYSTEM_UNKNOWN); - ECase(IMAGE_SUBSYSTEM_NATIVE); - ECase(IMAGE_SUBSYSTEM_WINDOWS_GUI); - ECase(IMAGE_SUBSYSTEM_WINDOWS_CUI); - ECase(IMAGE_SUBSYSTEM_OS2_CUI); - ECase(IMAGE_SUBSYSTEM_POSIX_CUI); - ECase(IMAGE_SUBSYSTEM_NATIVE_WINDOWS); - ECase(IMAGE_SUBSYSTEM_WINDOWS_CE_GUI); - ECase(IMAGE_SUBSYSTEM_EFI_APPLICATION); - ECase(IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER); - ECase(IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER); - ECase(IMAGE_SUBSYSTEM_EFI_ROM); - ECase(IMAGE_SUBSYSTEM_XBOX); - ECase(IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION); -} -#undef ECase - -#define BCase(X) IO.bitSetCase(Value, #X, COFF::X); -void ScalarBitSetTraits<COFF::Characteristics>::bitset( - IO &IO, COFF::Characteristics &Value) { - BCase(IMAGE_FILE_RELOCS_STRIPPED); - BCase(IMAGE_FILE_EXECUTABLE_IMAGE); - BCase(IMAGE_FILE_LINE_NUMS_STRIPPED); - BCase(IMAGE_FILE_LOCAL_SYMS_STRIPPED); - BCase(IMAGE_FILE_AGGRESSIVE_WS_TRIM); - BCase(IMAGE_FILE_LARGE_ADDRESS_AWARE); - BCase(IMAGE_FILE_BYTES_REVERSED_LO); - BCase(IMAGE_FILE_32BIT_MACHINE); - BCase(IMAGE_FILE_DEBUG_STRIPPED); - BCase(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP); - BCase(IMAGE_FILE_NET_RUN_FROM_SWAP); - BCase(IMAGE_FILE_SYSTEM); - BCase(IMAGE_FILE_DLL); - BCase(IMAGE_FILE_UP_SYSTEM_ONLY); - BCase(IMAGE_FILE_BYTES_REVERSED_HI); -} - -void ScalarBitSetTraits<COFF::SectionCharacteristics>::bitset( - IO &IO, COFF::SectionCharacteristics &Value) { - BCase(IMAGE_SCN_TYPE_NOLOAD); - BCase(IMAGE_SCN_TYPE_NO_PAD); - BCase(IMAGE_SCN_CNT_CODE); - BCase(IMAGE_SCN_CNT_INITIALIZED_DATA); - BCase(IMAGE_SCN_CNT_UNINITIALIZED_DATA); - BCase(IMAGE_SCN_LNK_OTHER); - BCase(IMAGE_SCN_LNK_INFO); - BCase(IMAGE_SCN_LNK_REMOVE); - BCase(IMAGE_SCN_LNK_COMDAT); - BCase(IMAGE_SCN_GPREL); - BCase(IMAGE_SCN_MEM_PURGEABLE); - BCase(IMAGE_SCN_MEM_16BIT); - BCase(IMAGE_SCN_MEM_LOCKED); - BCase(IMAGE_SCN_MEM_PRELOAD); - BCase(IMAGE_SCN_LNK_NRELOC_OVFL); - BCase(IMAGE_SCN_MEM_DISCARDABLE); - BCase(IMAGE_SCN_MEM_NOT_CACHED); - BCase(IMAGE_SCN_MEM_NOT_PAGED); - BCase(IMAGE_SCN_MEM_SHARED); - BCase(IMAGE_SCN_MEM_EXECUTE); - BCase(IMAGE_SCN_MEM_READ); - BCase(IMAGE_SCN_MEM_WRITE); -} - -void ScalarBitSetTraits<COFF::DLLCharacteristics>::bitset( - IO &IO, COFF::DLLCharacteristics &Value) { - BCase(IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA); - BCase(IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE); - BCase(IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY); - BCase(IMAGE_DLL_CHARACTERISTICS_NX_COMPAT); - BCase(IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION); - BCase(IMAGE_DLL_CHARACTERISTICS_NO_SEH); - BCase(IMAGE_DLL_CHARACTERISTICS_NO_BIND); - BCase(IMAGE_DLL_CHARACTERISTICS_APPCONTAINER); - BCase(IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER); - BCase(IMAGE_DLL_CHARACTERISTICS_GUARD_CF); - BCase(IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE); -} -#undef BCase - -namespace { -struct NSectionSelectionType { - NSectionSelectionType(IO &) - : SelectionType(COFFYAML::COMDATType(0)) {} - NSectionSelectionType(IO &, uint8_t C) - : SelectionType(COFFYAML::COMDATType(C)) {} - uint8_t denormalize(IO &) { return SelectionType; } - COFFYAML::COMDATType SelectionType; -}; - -struct NWeakExternalCharacteristics { - NWeakExternalCharacteristics(IO &) - : Characteristics(COFFYAML::WeakExternalCharacteristics(0)) {} - NWeakExternalCharacteristics(IO &, uint32_t C) - : Characteristics(COFFYAML::WeakExternalCharacteristics(C)) {} - uint32_t denormalize(IO &) { return Characteristics; } - COFFYAML::WeakExternalCharacteristics Characteristics; -}; - -struct NSectionCharacteristics { - NSectionCharacteristics(IO &) - : Characteristics(COFF::SectionCharacteristics(0)) {} - NSectionCharacteristics(IO &, uint32_t C) - : Characteristics(COFF::SectionCharacteristics(C)) {} - uint32_t denormalize(IO &) { return Characteristics; } - COFF::SectionCharacteristics Characteristics; -}; - -struct NAuxTokenType { - NAuxTokenType(IO &) - : AuxType(COFFYAML::AuxSymbolType(0)) {} - NAuxTokenType(IO &, uint8_t C) - : AuxType(COFFYAML::AuxSymbolType(C)) {} - uint32_t denormalize(IO &) { return AuxType; } - COFFYAML::AuxSymbolType AuxType; -}; - -struct NStorageClass { - NStorageClass(IO &) : StorageClass(COFF::SymbolStorageClass(0)) {} - NStorageClass(IO &, uint8_t S) : StorageClass(COFF::SymbolStorageClass(S)) {} - uint8_t denormalize(IO &) { return StorageClass; } - - COFF::SymbolStorageClass StorageClass; -}; - -struct NMachine { - NMachine(IO &) : Machine(COFF::MachineTypes(0)) {} - NMachine(IO &, uint16_t M) : Machine(COFF::MachineTypes(M)) {} - uint16_t denormalize(IO &) { return Machine; } - COFF::MachineTypes Machine; -}; - -struct NHeaderCharacteristics { - NHeaderCharacteristics(IO &) : Characteristics(COFF::Characteristics(0)) {} - NHeaderCharacteristics(IO &, uint16_t C) - : Characteristics(COFF::Characteristics(C)) {} - uint16_t denormalize(IO &) { return Characteristics; } - - COFF::Characteristics Characteristics; -}; - -template <typename RelocType> -struct NType { - NType(IO &) : Type(RelocType(0)) {} - NType(IO &, uint16_t T) : Type(RelocType(T)) {} - uint16_t denormalize(IO &) { return Type; } - RelocType Type; -}; - -struct NWindowsSubsystem { - NWindowsSubsystem(IO &) : Subsystem(COFF::WindowsSubsystem(0)) {} - NWindowsSubsystem(IO &, uint16_t C) : Subsystem(COFF::WindowsSubsystem(C)) {} - uint16_t denormalize(IO &) { return Subsystem; } - - COFF::WindowsSubsystem Subsystem; -}; - -struct NDLLCharacteristics { - NDLLCharacteristics(IO &) : Characteristics(COFF::DLLCharacteristics(0)) {} - NDLLCharacteristics(IO &, uint16_t C) - : Characteristics(COFF::DLLCharacteristics(C)) {} - uint16_t denormalize(IO &) { return Characteristics; } - - COFF::DLLCharacteristics Characteristics; -}; - -} - -void MappingTraits<COFFYAML::Relocation>::mapping(IO &IO, - COFFYAML::Relocation &Rel) { - IO.mapRequired("VirtualAddress", Rel.VirtualAddress); - IO.mapRequired("SymbolName", Rel.SymbolName); - - COFF::header &H = *static_cast<COFF::header *>(IO.getContext()); - if (H.Machine == COFF::IMAGE_FILE_MACHINE_I386) { - MappingNormalization<NType<COFF::RelocationTypeI386>, uint16_t> NT( - IO, Rel.Type); - IO.mapRequired("Type", NT->Type); - } else if (H.Machine == COFF::IMAGE_FILE_MACHINE_AMD64) { - MappingNormalization<NType<COFF::RelocationTypeAMD64>, uint16_t> NT( - IO, Rel.Type); - IO.mapRequired("Type", NT->Type); - } else { - IO.mapRequired("Type", Rel.Type); - } -} - -void MappingTraits<COFF::DataDirectory>::mapping(IO &IO, - COFF::DataDirectory &DD) { - IO.mapRequired("RelativeVirtualAddress", DD.RelativeVirtualAddress); - IO.mapRequired("Size", DD.Size); -} - -void MappingTraits<COFFYAML::PEHeader>::mapping(IO &IO, - COFFYAML::PEHeader &PH) { - MappingNormalization<NWindowsSubsystem, uint16_t> NWS(IO, - PH.Header.Subsystem); - MappingNormalization<NDLLCharacteristics, uint16_t> NDC( - IO, PH.Header.DLLCharacteristics); - - IO.mapRequired("AddressOfEntryPoint", PH.Header.AddressOfEntryPoint); - IO.mapRequired("ImageBase", PH.Header.ImageBase); - IO.mapRequired("SectionAlignment", PH.Header.SectionAlignment); - IO.mapRequired("FileAlignment", PH.Header.FileAlignment); - IO.mapRequired("MajorOperatingSystemVersion", - PH.Header.MajorOperatingSystemVersion); - IO.mapRequired("MinorOperatingSystemVersion", - PH.Header.MinorOperatingSystemVersion); - IO.mapRequired("MajorImageVersion", PH.Header.MajorImageVersion); - IO.mapRequired("MinorImageVersion", PH.Header.MinorImageVersion); - IO.mapRequired("MajorSubsystemVersion", PH.Header.MajorSubsystemVersion); - IO.mapRequired("MinorSubsystemVersion", PH.Header.MinorSubsystemVersion); - IO.mapRequired("Subsystem", NWS->Subsystem); - IO.mapRequired("DLLCharacteristics", NDC->Characteristics); - IO.mapRequired("SizeOfStackReserve", PH.Header.SizeOfStackReserve); - IO.mapRequired("SizeOfStackCommit", PH.Header.SizeOfStackCommit); - IO.mapRequired("SizeOfHeapReserve", PH.Header.SizeOfHeapReserve); - IO.mapRequired("SizeOfHeapCommit", PH.Header.SizeOfHeapCommit); - - IO.mapOptional("ExportTable", PH.DataDirectories[COFF::EXPORT_TABLE]); - IO.mapOptional("ImportTable", PH.DataDirectories[COFF::IMPORT_TABLE]); - IO.mapOptional("ResourceTable", PH.DataDirectories[COFF::RESOURCE_TABLE]); - IO.mapOptional("ExceptionTable", PH.DataDirectories[COFF::EXCEPTION_TABLE]); - IO.mapOptional("CertificateTable", PH.DataDirectories[COFF::CERTIFICATE_TABLE]); - IO.mapOptional("BaseRelocationTable", - PH.DataDirectories[COFF::BASE_RELOCATION_TABLE]); - IO.mapOptional("Debug", PH.DataDirectories[COFF::DEBUG]); - IO.mapOptional("Architecture", PH.DataDirectories[COFF::ARCHITECTURE]); - IO.mapOptional("GlobalPtr", PH.DataDirectories[COFF::GLOBAL_PTR]); - IO.mapOptional("TlsTable", PH.DataDirectories[COFF::TLS_TABLE]); - IO.mapOptional("LoadConfigTable", - PH.DataDirectories[COFF::LOAD_CONFIG_TABLE]); - IO.mapOptional("BoundImport", PH.DataDirectories[COFF::BOUND_IMPORT]); - IO.mapOptional("IAT", PH.DataDirectories[COFF::IAT]); - IO.mapOptional("DelayImportDescriptor", - PH.DataDirectories[COFF::DELAY_IMPORT_DESCRIPTOR]); - IO.mapOptional("ClrRuntimeHeader", - PH.DataDirectories[COFF::CLR_RUNTIME_HEADER]); -} - -void MappingTraits<COFF::header>::mapping(IO &IO, COFF::header &H) { - MappingNormalization<NMachine, uint16_t> NM(IO, H.Machine); - MappingNormalization<NHeaderCharacteristics, uint16_t> NC(IO, - H.Characteristics); - - IO.mapRequired("Machine", NM->Machine); - IO.mapOptional("Characteristics", NC->Characteristics); - IO.setContext(static_cast<void *>(&H)); -} - -void MappingTraits<COFF::AuxiliaryFunctionDefinition>::mapping( - IO &IO, COFF::AuxiliaryFunctionDefinition &AFD) { - IO.mapRequired("TagIndex", AFD.TagIndex); - IO.mapRequired("TotalSize", AFD.TotalSize); - IO.mapRequired("PointerToLinenumber", AFD.PointerToLinenumber); - IO.mapRequired("PointerToNextFunction", AFD.PointerToNextFunction); -} - -void MappingTraits<COFF::AuxiliarybfAndefSymbol>::mapping( - IO &IO, COFF::AuxiliarybfAndefSymbol &AAS) { - IO.mapRequired("Linenumber", AAS.Linenumber); - IO.mapRequired("PointerToNextFunction", AAS.PointerToNextFunction); -} - -void MappingTraits<COFF::AuxiliaryWeakExternal>::mapping( - IO &IO, COFF::AuxiliaryWeakExternal &AWE) { - MappingNormalization<NWeakExternalCharacteristics, uint32_t> NWEC( - IO, AWE.Characteristics); - IO.mapRequired("TagIndex", AWE.TagIndex); - IO.mapRequired("Characteristics", NWEC->Characteristics); -} - -void MappingTraits<COFF::AuxiliarySectionDefinition>::mapping( - IO &IO, COFF::AuxiliarySectionDefinition &ASD) { - MappingNormalization<NSectionSelectionType, uint8_t> NSST( - IO, ASD.Selection); - - IO.mapRequired("Length", ASD.Length); - IO.mapRequired("NumberOfRelocations", ASD.NumberOfRelocations); - IO.mapRequired("NumberOfLinenumbers", ASD.NumberOfLinenumbers); - IO.mapRequired("CheckSum", ASD.CheckSum); - IO.mapRequired("Number", ASD.Number); - IO.mapOptional("Selection", NSST->SelectionType, COFFYAML::COMDATType(0)); -} - -void MappingTraits<COFF::AuxiliaryCLRToken>::mapping( - IO &IO, COFF::AuxiliaryCLRToken &ACT) { - MappingNormalization<NAuxTokenType, uint8_t> NATT(IO, ACT.AuxType); - IO.mapRequired("AuxType", NATT->AuxType); - IO.mapRequired("SymbolTableIndex", ACT.SymbolTableIndex); -} - -void MappingTraits<COFFYAML::Symbol>::mapping(IO &IO, COFFYAML::Symbol &S) { - MappingNormalization<NStorageClass, uint8_t> NS(IO, S.Header.StorageClass); - - IO.mapRequired("Name", S.Name); - IO.mapRequired("Value", S.Header.Value); - IO.mapRequired("SectionNumber", S.Header.SectionNumber); - IO.mapRequired("SimpleType", S.SimpleType); - IO.mapRequired("ComplexType", S.ComplexType); - IO.mapRequired("StorageClass", NS->StorageClass); - IO.mapOptional("FunctionDefinition", S.FunctionDefinition); - IO.mapOptional("bfAndefSymbol", S.bfAndefSymbol); - IO.mapOptional("WeakExternal", S.WeakExternal); - IO.mapOptional("File", S.File, StringRef()); - IO.mapOptional("SectionDefinition", S.SectionDefinition); - IO.mapOptional("CLRToken", S.CLRToken); -} - -void MappingTraits<COFFYAML::Section>::mapping(IO &IO, COFFYAML::Section &Sec) { - MappingNormalization<NSectionCharacteristics, uint32_t> NC( - IO, Sec.Header.Characteristics); - IO.mapRequired("Name", Sec.Name); - IO.mapRequired("Characteristics", NC->Characteristics); - IO.mapOptional("VirtualAddress", Sec.Header.VirtualAddress, 0U); - IO.mapOptional("VirtualSize", Sec.Header.VirtualSize, 0U); - IO.mapOptional("Alignment", Sec.Alignment); - IO.mapRequired("SectionData", Sec.SectionData); - IO.mapOptional("Relocations", Sec.Relocations); -} - -void MappingTraits<COFFYAML::Object>::mapping(IO &IO, COFFYAML::Object &Obj) { - IO.mapOptional("OptionalHeader", Obj.OptionalHeader); - IO.mapRequired("header", Obj.Header); - IO.mapRequired("sections", Obj.Sections); - IO.mapRequired("symbols", Obj.Symbols); -} - -} -} diff --git a/gnu/llvm/lib/Object/ELFYAML.cpp b/gnu/llvm/lib/Object/ELFYAML.cpp deleted file mode 100644 index 4a4b2276f46..00000000000 --- a/gnu/llvm/lib/Object/ELFYAML.cpp +++ /dev/null @@ -1,809 +0,0 @@ -//===- ELFYAML.cpp - ELF YAMLIO implementation ----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines classes for handling the YAML representation of ELF. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Object/ELFYAML.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/MipsABIFlags.h" - -namespace llvm { - -ELFYAML::Section::~Section() {} - -namespace yaml { - -void -ScalarEnumerationTraits<ELFYAML::ELF_ET>::enumeration(IO &IO, - ELFYAML::ELF_ET &Value) { -#define ECase(X) IO.enumCase(Value, #X, ELF::X); - ECase(ET_NONE) - ECase(ET_REL) - ECase(ET_EXEC) - ECase(ET_DYN) - ECase(ET_CORE) -#undef ECase - IO.enumFallback<Hex16>(Value); -} - -void -ScalarEnumerationTraits<ELFYAML::ELF_EM>::enumeration(IO &IO, - ELFYAML::ELF_EM &Value) { -#define ECase(X) IO.enumCase(Value, #X, ELF::X); - ECase(EM_NONE) - ECase(EM_M32) - ECase(EM_SPARC) - ECase(EM_386) - ECase(EM_68K) - ECase(EM_88K) - ECase(EM_IAMCU) - ECase(EM_860) - ECase(EM_MIPS) - ECase(EM_S370) - ECase(EM_MIPS_RS3_LE) - ECase(EM_PARISC) - ECase(EM_VPP500) - ECase(EM_SPARC32PLUS) - ECase(EM_960) - ECase(EM_PPC) - ECase(EM_PPC64) - ECase(EM_S390) - ECase(EM_SPU) - ECase(EM_V800) - ECase(EM_FR20) - ECase(EM_RH32) - ECase(EM_RCE) - ECase(EM_ARM) - ECase(EM_ALPHA) - ECase(EM_SH) - ECase(EM_SPARCV9) - ECase(EM_TRICORE) - ECase(EM_ARC) - ECase(EM_H8_300) - ECase(EM_H8_300H) - ECase(EM_H8S) - ECase(EM_H8_500) - ECase(EM_IA_64) - ECase(EM_MIPS_X) - ECase(EM_COLDFIRE) - ECase(EM_68HC12) - ECase(EM_MMA) - ECase(EM_PCP) - ECase(EM_NCPU) - ECase(EM_NDR1) - ECase(EM_STARCORE) - ECase(EM_ME16) - ECase(EM_ST100) - ECase(EM_TINYJ) - ECase(EM_X86_64) - ECase(EM_PDSP) - ECase(EM_PDP10) - ECase(EM_PDP11) - ECase(EM_FX66) - ECase(EM_ST9PLUS) - ECase(EM_ST7) - ECase(EM_68HC16) - ECase(EM_68HC11) - ECase(EM_68HC08) - ECase(EM_68HC05) - ECase(EM_SVX) - ECase(EM_ST19) - ECase(EM_VAX) - ECase(EM_CRIS) - ECase(EM_JAVELIN) - ECase(EM_FIREPATH) - ECase(EM_ZSP) - ECase(EM_MMIX) - ECase(EM_HUANY) - ECase(EM_PRISM) - ECase(EM_AVR) - ECase(EM_FR30) - ECase(EM_D10V) - ECase(EM_D30V) - ECase(EM_V850) - ECase(EM_M32R) - ECase(EM_MN10300) - ECase(EM_MN10200) - ECase(EM_PJ) - ECase(EM_OPENRISC) - ECase(EM_ARC_COMPACT) - ECase(EM_XTENSA) - ECase(EM_VIDEOCORE) - ECase(EM_TMM_GPP) - ECase(EM_NS32K) - ECase(EM_TPC) - ECase(EM_SNP1K) - ECase(EM_ST200) - ECase(EM_IP2K) - ECase(EM_MAX) - ECase(EM_CR) - ECase(EM_F2MC16) - ECase(EM_MSP430) - ECase(EM_BLACKFIN) - ECase(EM_SE_C33) - ECase(EM_SEP) - ECase(EM_ARCA) - ECase(EM_UNICORE) - ECase(EM_EXCESS) - ECase(EM_DXP) - ECase(EM_ALTERA_NIOS2) - ECase(EM_CRX) - ECase(EM_XGATE) - ECase(EM_C166) - ECase(EM_M16C) - ECase(EM_DSPIC30F) - ECase(EM_CE) - ECase(EM_M32C) - ECase(EM_TSK3000) - ECase(EM_RS08) - ECase(EM_SHARC) - ECase(EM_ECOG2) - ECase(EM_SCORE7) - ECase(EM_DSP24) - ECase(EM_VIDEOCORE3) - ECase(EM_LATTICEMICO32) - ECase(EM_SE_C17) - ECase(EM_TI_C6000) - ECase(EM_TI_C2000) - ECase(EM_TI_C5500) - ECase(EM_MMDSP_PLUS) - ECase(EM_CYPRESS_M8C) - ECase(EM_R32C) - ECase(EM_TRIMEDIA) - ECase(EM_HEXAGON) - ECase(EM_8051) - ECase(EM_STXP7X) - ECase(EM_NDS32) - ECase(EM_ECOG1) - ECase(EM_ECOG1X) - ECase(EM_MAXQ30) - ECase(EM_XIMO16) - ECase(EM_MANIK) - ECase(EM_CRAYNV2) - ECase(EM_RX) - ECase(EM_METAG) - ECase(EM_MCST_ELBRUS) - ECase(EM_ECOG16) - ECase(EM_CR16) - ECase(EM_ETPU) - ECase(EM_SLE9X) - ECase(EM_L10M) - ECase(EM_K10M) - ECase(EM_AARCH64) - ECase(EM_AVR32) - ECase(EM_STM8) - ECase(EM_TILE64) - ECase(EM_TILEPRO) - ECase(EM_CUDA) - ECase(EM_TILEGX) - ECase(EM_CLOUDSHIELD) - ECase(EM_COREA_1ST) - ECase(EM_COREA_2ND) - ECase(EM_ARC_COMPACT2) - ECase(EM_OPEN8) - ECase(EM_RL78) - ECase(EM_VIDEOCORE5) - ECase(EM_78KOR) - ECase(EM_56800EX) - ECase(EM_AMDGPU) -#undef ECase -} - -void ScalarEnumerationTraits<ELFYAML::ELF_ELFCLASS>::enumeration( - IO &IO, ELFYAML::ELF_ELFCLASS &Value) { -#define ECase(X) IO.enumCase(Value, #X, ELF::X); - // Since the semantics of ELFCLASSNONE is "invalid", just don't accept it - // here. - ECase(ELFCLASS32) - ECase(ELFCLASS64) -#undef ECase -} - -void ScalarEnumerationTraits<ELFYAML::ELF_ELFDATA>::enumeration( - IO &IO, ELFYAML::ELF_ELFDATA &Value) { -#define ECase(X) IO.enumCase(Value, #X, ELF::X); - // Since the semantics of ELFDATANONE is "invalid", just don't accept it - // here. - ECase(ELFDATA2LSB) - ECase(ELFDATA2MSB) -#undef ECase -} - -void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration( - IO &IO, ELFYAML::ELF_ELFOSABI &Value) { -#define ECase(X) IO.enumCase(Value, #X, ELF::X); - ECase(ELFOSABI_NONE) - ECase(ELFOSABI_HPUX) - ECase(ELFOSABI_NETBSD) - ECase(ELFOSABI_GNU) - ECase(ELFOSABI_GNU) - ECase(ELFOSABI_HURD) - ECase(ELFOSABI_SOLARIS) - ECase(ELFOSABI_AIX) - ECase(ELFOSABI_IRIX) - ECase(ELFOSABI_FREEBSD) - ECase(ELFOSABI_TRU64) - ECase(ELFOSABI_MODESTO) - ECase(ELFOSABI_OPENBSD) - ECase(ELFOSABI_OPENVMS) - ECase(ELFOSABI_NSK) - ECase(ELFOSABI_AROS) - ECase(ELFOSABI_FENIXOS) - ECase(ELFOSABI_CLOUDABI) - ECase(ELFOSABI_C6000_ELFABI) - ECase(ELFOSABI_C6000_LINUX) - ECase(ELFOSABI_ARM) - ECase(ELFOSABI_STANDALONE) -#undef ECase -} - -void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO, - ELFYAML::ELF_EF &Value) { - const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); - assert(Object && "The IO context is not initialized"); -#define BCase(X) IO.bitSetCase(Value, #X, ELF::X); -#define BCaseMask(X, M) IO.maskedBitSetCase(Value, #X, ELF::X, ELF::M); - switch (Object->Header.Machine) { - case ELF::EM_ARM: - BCase(EF_ARM_SOFT_FLOAT) - BCase(EF_ARM_VFP_FLOAT) - BCaseMask(EF_ARM_EABI_UNKNOWN, EF_ARM_EABIMASK) - BCaseMask(EF_ARM_EABI_VER1, EF_ARM_EABIMASK) - BCaseMask(EF_ARM_EABI_VER2, EF_ARM_EABIMASK) - BCaseMask(EF_ARM_EABI_VER3, EF_ARM_EABIMASK) - BCaseMask(EF_ARM_EABI_VER4, EF_ARM_EABIMASK) - BCaseMask(EF_ARM_EABI_VER5, EF_ARM_EABIMASK) - break; - case ELF::EM_MIPS: - BCase(EF_MIPS_NOREORDER) - BCase(EF_MIPS_PIC) - BCase(EF_MIPS_CPIC) - BCase(EF_MIPS_ABI2) - BCase(EF_MIPS_32BITMODE) - BCase(EF_MIPS_FP64) - BCase(EF_MIPS_NAN2008) - BCase(EF_MIPS_MICROMIPS) - BCase(EF_MIPS_ARCH_ASE_M16) - BCase(EF_MIPS_ARCH_ASE_MDMX) - BCaseMask(EF_MIPS_ABI_O32, EF_MIPS_ABI) - BCaseMask(EF_MIPS_ABI_O64, EF_MIPS_ABI) - BCaseMask(EF_MIPS_ABI_EABI32, EF_MIPS_ABI) - BCaseMask(EF_MIPS_ABI_EABI64, EF_MIPS_ABI) - BCaseMask(EF_MIPS_MACH_3900, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_4010, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_4100, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_4650, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_4120, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_4111, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_SB1, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_OCTEON, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_XLR, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_OCTEON2, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_OCTEON3, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_5400, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_5900, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_5500, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_9000, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_LS2E, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_LS2F, EF_MIPS_MACH) - BCaseMask(EF_MIPS_MACH_LS3A, EF_MIPS_MACH) - BCaseMask(EF_MIPS_ARCH_1, EF_MIPS_ARCH) - BCaseMask(EF_MIPS_ARCH_2, EF_MIPS_ARCH) - BCaseMask(EF_MIPS_ARCH_3, EF_MIPS_ARCH) - BCaseMask(EF_MIPS_ARCH_4, EF_MIPS_ARCH) - BCaseMask(EF_MIPS_ARCH_5, EF_MIPS_ARCH) - BCaseMask(EF_MIPS_ARCH_32, EF_MIPS_ARCH) - BCaseMask(EF_MIPS_ARCH_64, EF_MIPS_ARCH) - BCaseMask(EF_MIPS_ARCH_32R2, EF_MIPS_ARCH) - BCaseMask(EF_MIPS_ARCH_64R2, EF_MIPS_ARCH) - BCaseMask(EF_MIPS_ARCH_32R6, EF_MIPS_ARCH) - BCaseMask(EF_MIPS_ARCH_64R6, EF_MIPS_ARCH) - break; - case ELF::EM_HEXAGON: - BCase(EF_HEXAGON_MACH_V2) - BCase(EF_HEXAGON_MACH_V3) - BCase(EF_HEXAGON_MACH_V4) - BCase(EF_HEXAGON_MACH_V5) - BCase(EF_HEXAGON_ISA_V2) - BCase(EF_HEXAGON_ISA_V3) - BCase(EF_HEXAGON_ISA_V4) - BCase(EF_HEXAGON_ISA_V5) - break; - case ELF::EM_AVR: - BCase(EF_AVR_ARCH_AVR1) - BCase(EF_AVR_ARCH_AVR2) - BCase(EF_AVR_ARCH_AVR25) - BCase(EF_AVR_ARCH_AVR3) - BCase(EF_AVR_ARCH_AVR31) - BCase(EF_AVR_ARCH_AVR35) - BCase(EF_AVR_ARCH_AVR4) - BCase(EF_AVR_ARCH_AVR51) - BCase(EF_AVR_ARCH_AVR6) - BCase(EF_AVR_ARCH_AVRTINY) - BCase(EF_AVR_ARCH_XMEGA1) - BCase(EF_AVR_ARCH_XMEGA2) - BCase(EF_AVR_ARCH_XMEGA3) - BCase(EF_AVR_ARCH_XMEGA4) - BCase(EF_AVR_ARCH_XMEGA5) - BCase(EF_AVR_ARCH_XMEGA6) - BCase(EF_AVR_ARCH_XMEGA7) - break; - default: - llvm_unreachable("Unsupported architecture"); - } -#undef BCase -#undef BCaseMask -} - -void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration( - IO &IO, ELFYAML::ELF_SHT &Value) { - const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); - assert(Object && "The IO context is not initialized"); -#define ECase(X) IO.enumCase(Value, #X, ELF::X); - ECase(SHT_NULL) - ECase(SHT_PROGBITS) - // No SHT_SYMTAB. Use the top-level `Symbols` key instead. - // FIXME: Issue a diagnostic with this information. - ECase(SHT_STRTAB) - ECase(SHT_RELA) - ECase(SHT_HASH) - ECase(SHT_DYNAMIC) - ECase(SHT_NOTE) - ECase(SHT_NOBITS) - ECase(SHT_REL) - ECase(SHT_SHLIB) - ECase(SHT_DYNSYM) - ECase(SHT_INIT_ARRAY) - ECase(SHT_FINI_ARRAY) - ECase(SHT_PREINIT_ARRAY) - ECase(SHT_GROUP) - ECase(SHT_SYMTAB_SHNDX) - ECase(SHT_LOOS) - ECase(SHT_GNU_ATTRIBUTES) - ECase(SHT_GNU_HASH) - ECase(SHT_GNU_verdef) - ECase(SHT_GNU_verneed) - ECase(SHT_GNU_versym) - ECase(SHT_HIOS) - ECase(SHT_LOPROC) - switch (Object->Header.Machine) { - case ELF::EM_ARM: - ECase(SHT_ARM_EXIDX) - ECase(SHT_ARM_PREEMPTMAP) - ECase(SHT_ARM_ATTRIBUTES) - ECase(SHT_ARM_DEBUGOVERLAY) - ECase(SHT_ARM_OVERLAYSECTION) - break; - case ELF::EM_HEXAGON: - ECase(SHT_HEX_ORDERED) - break; - case ELF::EM_X86_64: - ECase(SHT_X86_64_UNWIND) - break; - case ELF::EM_MIPS: - ECase(SHT_MIPS_REGINFO) - ECase(SHT_MIPS_OPTIONS) - ECase(SHT_MIPS_ABIFLAGS) - break; - default: - // Nothing to do. - break; - } -#undef ECase -} - -void ScalarBitSetTraits<ELFYAML::ELF_SHF>::bitset(IO &IO, - ELFYAML::ELF_SHF &Value) { - const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); -#define BCase(X) IO.bitSetCase(Value, #X, ELF::X); - BCase(SHF_WRITE) - BCase(SHF_ALLOC) - BCase(SHF_EXCLUDE) - BCase(SHF_EXECINSTR) - BCase(SHF_MERGE) - BCase(SHF_STRINGS) - BCase(SHF_INFO_LINK) - BCase(SHF_LINK_ORDER) - BCase(SHF_OS_NONCONFORMING) - BCase(SHF_GROUP) - BCase(SHF_TLS) - switch(Object->Header.Machine) { - case ELF::EM_AMDGPU: - BCase(SHF_AMDGPU_HSA_GLOBAL) - BCase(SHF_AMDGPU_HSA_READONLY) - BCase(SHF_AMDGPU_HSA_CODE) - BCase(SHF_AMDGPU_HSA_AGENT) - break; - default: - // Nothing to do. - break; - } -#undef BCase -} - -void ScalarEnumerationTraits<ELFYAML::ELF_STT>::enumeration( - IO &IO, ELFYAML::ELF_STT &Value) { -#define ECase(X) IO.enumCase(Value, #X, ELF::X); - ECase(STT_NOTYPE) - ECase(STT_OBJECT) - ECase(STT_FUNC) - ECase(STT_SECTION) - ECase(STT_FILE) - ECase(STT_COMMON) - ECase(STT_TLS) - ECase(STT_GNU_IFUNC) -#undef ECase -} - -void ScalarEnumerationTraits<ELFYAML::ELF_STV>::enumeration( - IO &IO, ELFYAML::ELF_STV &Value) { -#define ECase(X) IO.enumCase(Value, #X, ELF::X); - ECase(STV_DEFAULT) - ECase(STV_INTERNAL) - ECase(STV_HIDDEN) - ECase(STV_PROTECTED) -#undef ECase -} - -void ScalarBitSetTraits<ELFYAML::ELF_STO>::bitset(IO &IO, - ELFYAML::ELF_STO &Value) { - const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); - assert(Object && "The IO context is not initialized"); -#define BCase(X) IO.bitSetCase(Value, #X, ELF::X); - switch (Object->Header.Machine) { - case ELF::EM_MIPS: - BCase(STO_MIPS_OPTIONAL) - BCase(STO_MIPS_PLT) - BCase(STO_MIPS_PIC) - BCase(STO_MIPS_MICROMIPS) - break; - default: - break; // Nothing to do - } -#undef BCase -#undef BCaseMask -} - -void ScalarEnumerationTraits<ELFYAML::ELF_RSS>::enumeration( - IO &IO, ELFYAML::ELF_RSS &Value) { -#define ECase(X) IO.enumCase(Value, #X, ELF::X); - ECase(RSS_UNDEF) - ECase(RSS_GP) - ECase(RSS_GP0) - ECase(RSS_LOC) -#undef ECase -} - -void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration( - IO &IO, ELFYAML::ELF_REL &Value) { - const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); - assert(Object && "The IO context is not initialized"); -#define ELF_RELOC(X, Y) IO.enumCase(Value, #X, ELF::X); - switch (Object->Header.Machine) { - case ELF::EM_X86_64: -#include "llvm/Support/ELFRelocs/x86_64.def" - break; - case ELF::EM_MIPS: -#include "llvm/Support/ELFRelocs/Mips.def" - break; - case ELF::EM_HEXAGON: -#include "llvm/Support/ELFRelocs/Hexagon.def" - break; - case ELF::EM_386: - case ELF::EM_IAMCU: -#include "llvm/Support/ELFRelocs/i386.def" - break; - case ELF::EM_AARCH64: -#include "llvm/Support/ELFRelocs/AArch64.def" - break; - case ELF::EM_ARM: -#include "llvm/Support/ELFRelocs/ARM.def" - break; - default: - llvm_unreachable("Unsupported architecture"); - } -#undef ELF_RELOC -} - -void ScalarEnumerationTraits<ELFYAML::MIPS_AFL_REG>::enumeration( - IO &IO, ELFYAML::MIPS_AFL_REG &Value) { -#define ECase(X) IO.enumCase(Value, #X, Mips::AFL_##X); - ECase(REG_NONE) - ECase(REG_32) - ECase(REG_64) - ECase(REG_128) -#undef ECase -} - -void ScalarEnumerationTraits<ELFYAML::MIPS_ABI_FP>::enumeration( - IO &IO, ELFYAML::MIPS_ABI_FP &Value) { -#define ECase(X) IO.enumCase(Value, #X, Mips::Val_GNU_MIPS_ABI_##X); - ECase(FP_ANY) - ECase(FP_DOUBLE) - ECase(FP_SINGLE) - ECase(FP_SOFT) - ECase(FP_OLD_64) - ECase(FP_XX) - ECase(FP_64) - ECase(FP_64A) -#undef ECase -} - -void ScalarEnumerationTraits<ELFYAML::MIPS_AFL_EXT>::enumeration( - IO &IO, ELFYAML::MIPS_AFL_EXT &Value) { -#define ECase(X) IO.enumCase(Value, #X, Mips::AFL_##X); - ECase(EXT_NONE) - ECase(EXT_XLR) - ECase(EXT_OCTEON2) - ECase(EXT_OCTEONP) - ECase(EXT_LOONGSON_3A) - ECase(EXT_OCTEON) - ECase(EXT_5900) - ECase(EXT_4650) - ECase(EXT_4010) - ECase(EXT_4100) - ECase(EXT_3900) - ECase(EXT_10000) - ECase(EXT_SB1) - ECase(EXT_4111) - ECase(EXT_4120) - ECase(EXT_5400) - ECase(EXT_5500) - ECase(EXT_LOONGSON_2E) - ECase(EXT_LOONGSON_2F) - ECase(EXT_OCTEON3) -#undef ECase -} - -void ScalarEnumerationTraits<ELFYAML::MIPS_ISA>::enumeration( - IO &IO, ELFYAML::MIPS_ISA &Value) { - IO.enumCase(Value, "MIPS1", 1); - IO.enumCase(Value, "MIPS2", 2); - IO.enumCase(Value, "MIPS3", 3); - IO.enumCase(Value, "MIPS4", 4); - IO.enumCase(Value, "MIPS5", 5); - IO.enumCase(Value, "MIPS32", 32); - IO.enumCase(Value, "MIPS64", 64); -} - -void ScalarBitSetTraits<ELFYAML::MIPS_AFL_ASE>::bitset( - IO &IO, ELFYAML::MIPS_AFL_ASE &Value) { -#define BCase(X) IO.bitSetCase(Value, #X, Mips::AFL_ASE_##X); - BCase(DSP) - BCase(DSPR2) - BCase(EVA) - BCase(MCU) - BCase(MDMX) - BCase(MIPS3D) - BCase(MT) - BCase(SMARTMIPS) - BCase(VIRT) - BCase(MSA) - BCase(MIPS16) - BCase(MICROMIPS) - BCase(XPA) -#undef BCase -} - -void ScalarBitSetTraits<ELFYAML::MIPS_AFL_FLAGS1>::bitset( - IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value) { -#define BCase(X) IO.bitSetCase(Value, #X, Mips::AFL_FLAGS1_##X); - BCase(ODDSPREG) -#undef BCase -} - -void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO, - ELFYAML::FileHeader &FileHdr) { - IO.mapRequired("Class", FileHdr.Class); - IO.mapRequired("Data", FileHdr.Data); - IO.mapOptional("OSABI", FileHdr.OSABI, ELFYAML::ELF_ELFOSABI(0)); - IO.mapRequired("Type", FileHdr.Type); - IO.mapRequired("Machine", FileHdr.Machine); - IO.mapOptional("Flags", FileHdr.Flags, ELFYAML::ELF_EF(0)); - IO.mapOptional("Entry", FileHdr.Entry, Hex64(0)); -} - -namespace { -struct NormalizedOther { - NormalizedOther(IO &) - : Visibility(ELFYAML::ELF_STV(0)), Other(ELFYAML::ELF_STO(0)) {} - NormalizedOther(IO &, uint8_t Original) - : Visibility(Original & 0x3), Other(Original & ~0x3) {} - - uint8_t denormalize(IO &) { return Visibility | Other; } - - ELFYAML::ELF_STV Visibility; - ELFYAML::ELF_STO Other; -}; -} - -void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) { - IO.mapOptional("Name", Symbol.Name, StringRef()); - IO.mapOptional("Type", Symbol.Type, ELFYAML::ELF_STT(0)); - IO.mapOptional("Section", Symbol.Section, StringRef()); - IO.mapOptional("Value", Symbol.Value, Hex64(0)); - IO.mapOptional("Size", Symbol.Size, Hex64(0)); - - MappingNormalization<NormalizedOther, uint8_t> Keys(IO, Symbol.Other); - IO.mapOptional("Visibility", Keys->Visibility, ELFYAML::ELF_STV(0)); - IO.mapOptional("Other", Keys->Other, ELFYAML::ELF_STO(0)); -} - -void MappingTraits<ELFYAML::LocalGlobalWeakSymbols>::mapping( - IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols) { - IO.mapOptional("Local", Symbols.Local); - IO.mapOptional("Global", Symbols.Global); - IO.mapOptional("Weak", Symbols.Weak); -} - -static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) { - IO.mapOptional("Name", Section.Name, StringRef()); - IO.mapRequired("Type", Section.Type); - IO.mapOptional("Flags", Section.Flags, ELFYAML::ELF_SHF(0)); - IO.mapOptional("Address", Section.Address, Hex64(0)); - IO.mapOptional("Link", Section.Link, StringRef()); - IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0)); - IO.mapOptional("Info", Section.Info, StringRef()); -} - -static void sectionMapping(IO &IO, ELFYAML::RawContentSection &Section) { - commonSectionMapping(IO, Section); - IO.mapOptional("Content", Section.Content); - IO.mapOptional("Size", Section.Size, Hex64(Section.Content.binary_size())); -} - -static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { - commonSectionMapping(IO, Section); - IO.mapOptional("Size", Section.Size, Hex64(0)); -} - -static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) { - commonSectionMapping(IO, Section); - IO.mapOptional("Relocations", Section.Relocations); -} - -static void groupSectionMapping(IO &IO, ELFYAML::Group &group) { - commonSectionMapping(IO, group); - IO.mapRequired("Members", group.Members); -} - -void MappingTraits<ELFYAML::SectionOrType>::mapping( - IO &IO, ELFYAML::SectionOrType §ionOrType) { - IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType); -} - -static void sectionMapping(IO &IO, ELFYAML::MipsABIFlags &Section) { - commonSectionMapping(IO, Section); - IO.mapOptional("Version", Section.Version, Hex16(0)); - IO.mapRequired("ISA", Section.ISALevel); - IO.mapOptional("ISARevision", Section.ISARevision, Hex8(0)); - IO.mapOptional("ISAExtension", Section.ISAExtension, - ELFYAML::MIPS_AFL_EXT(Mips::AFL_EXT_NONE)); - IO.mapOptional("ASEs", Section.ASEs, ELFYAML::MIPS_AFL_ASE(0)); - IO.mapOptional("FpABI", Section.FpABI, - ELFYAML::MIPS_ABI_FP(Mips::Val_GNU_MIPS_ABI_FP_ANY)); - IO.mapOptional("GPRSize", Section.GPRSize, - ELFYAML::MIPS_AFL_REG(Mips::AFL_REG_NONE)); - IO.mapOptional("CPR1Size", Section.CPR1Size, - ELFYAML::MIPS_AFL_REG(Mips::AFL_REG_NONE)); - IO.mapOptional("CPR2Size", Section.CPR2Size, - ELFYAML::MIPS_AFL_REG(Mips::AFL_REG_NONE)); - IO.mapOptional("Flags1", Section.Flags1, ELFYAML::MIPS_AFL_FLAGS1(0)); - IO.mapOptional("Flags2", Section.Flags2, Hex32(0)); -} - -void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( - IO &IO, std::unique_ptr<ELFYAML::Section> &Section) { - ELFYAML::ELF_SHT sectionType; - if (IO.outputting()) - sectionType = Section->Type; - else - IO.mapRequired("Type", sectionType); - - switch (sectionType) { - case ELF::SHT_REL: - case ELF::SHT_RELA: - if (!IO.outputting()) - Section.reset(new ELFYAML::RelocationSection()); - sectionMapping(IO, *cast<ELFYAML::RelocationSection>(Section.get())); - break; - case ELF::SHT_GROUP: - if (!IO.outputting()) - Section.reset(new ELFYAML::Group()); - groupSectionMapping(IO, *cast<ELFYAML::Group>(Section.get())); - break; - case ELF::SHT_NOBITS: - if (!IO.outputting()) - Section.reset(new ELFYAML::NoBitsSection()); - sectionMapping(IO, *cast<ELFYAML::NoBitsSection>(Section.get())); - break; - case ELF::SHT_MIPS_ABIFLAGS: - if (!IO.outputting()) - Section.reset(new ELFYAML::MipsABIFlags()); - sectionMapping(IO, *cast<ELFYAML::MipsABIFlags>(Section.get())); - break; - default: - if (!IO.outputting()) - Section.reset(new ELFYAML::RawContentSection()); - sectionMapping(IO, *cast<ELFYAML::RawContentSection>(Section.get())); - } -} - -StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( - IO &io, std::unique_ptr<ELFYAML::Section> &Section) { - const auto *RawSection = dyn_cast<ELFYAML::RawContentSection>(Section.get()); - if (!RawSection || RawSection->Size >= RawSection->Content.binary_size()) - return StringRef(); - return "Section size must be greater or equal to the content size"; -} - -namespace { -struct NormalizedMips64RelType { - NormalizedMips64RelType(IO &) - : Type(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)), - Type2(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)), - Type3(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)), - SpecSym(ELFYAML::ELF_REL(ELF::RSS_UNDEF)) {} - NormalizedMips64RelType(IO &, ELFYAML::ELF_REL Original) - : Type(Original & 0xFF), Type2(Original >> 8 & 0xFF), - Type3(Original >> 16 & 0xFF), SpecSym(Original >> 24 & 0xFF) {} - - ELFYAML::ELF_REL denormalize(IO &) { - ELFYAML::ELF_REL Res = Type | Type2 << 8 | Type3 << 16 | SpecSym << 24; - return Res; - } - - ELFYAML::ELF_REL Type; - ELFYAML::ELF_REL Type2; - ELFYAML::ELF_REL Type3; - ELFYAML::ELF_RSS SpecSym; -}; -} - -void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO, - ELFYAML::Relocation &Rel) { - const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); - assert(Object && "The IO context is not initialized"); - - IO.mapRequired("Offset", Rel.Offset); - IO.mapRequired("Symbol", Rel.Symbol); - - if (Object->Header.Machine == ELFYAML::ELF_EM(ELF::EM_MIPS) && - Object->Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64)) { - MappingNormalization<NormalizedMips64RelType, ELFYAML::ELF_REL> Key( - IO, Rel.Type); - IO.mapRequired("Type", Key->Type); - IO.mapOptional("Type2", Key->Type2, ELFYAML::ELF_REL(ELF::R_MIPS_NONE)); - IO.mapOptional("Type3", Key->Type3, ELFYAML::ELF_REL(ELF::R_MIPS_NONE)); - IO.mapOptional("SpecSym", Key->SpecSym, ELFYAML::ELF_RSS(ELF::RSS_UNDEF)); - } else - IO.mapRequired("Type", Rel.Type); - - IO.mapOptional("Addend", Rel.Addend, (int64_t)0); -} - -void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) { - assert(!IO.getContext() && "The IO context is initialized already"); - IO.setContext(&Object); - IO.mapRequired("FileHeader", Object.Header); - IO.mapOptional("Sections", Object.Sections); - IO.mapOptional("Symbols", Object.Symbols); - IO.setContext(nullptr); -} - -LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP) -LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT) -LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE) -LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1) - -} // end namespace yaml -} // end namespace llvm diff --git a/gnu/llvm/lib/Object/FunctionIndexObjectFile.cpp b/gnu/llvm/lib/Object/FunctionIndexObjectFile.cpp deleted file mode 100644 index fe111de1a9c..00000000000 --- a/gnu/llvm/lib/Object/FunctionIndexObjectFile.cpp +++ /dev/null @@ -1,143 +0,0 @@ -//===- FunctionIndexObjectFile.cpp - Function index file implementation ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Part of the FunctionIndexObjectFile class implementation. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Object/FunctionIndexObjectFile.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/IR/FunctionInfo.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; -using namespace object; - -FunctionIndexObjectFile::FunctionIndexObjectFile( - MemoryBufferRef Object, std::unique_ptr<FunctionInfoIndex> I) - : SymbolicFile(Binary::ID_FunctionIndex, Object), Index(std::move(I)) {} - -FunctionIndexObjectFile::~FunctionIndexObjectFile() {} - -std::unique_ptr<FunctionInfoIndex> FunctionIndexObjectFile::takeIndex() { - return std::move(Index); -} - -ErrorOr<MemoryBufferRef> -FunctionIndexObjectFile::findBitcodeInObject(const ObjectFile &Obj) { - for (const SectionRef &Sec : Obj.sections()) { - StringRef SecName; - if (std::error_code EC = Sec.getName(SecName)) - return EC; - if (SecName == ".llvmbc") { - StringRef SecContents; - if (std::error_code EC = Sec.getContents(SecContents)) - return EC; - return MemoryBufferRef(SecContents, Obj.getFileName()); - } - } - - return object_error::bitcode_section_not_found; -} - -ErrorOr<MemoryBufferRef> -FunctionIndexObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { - sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); - switch (Type) { - case sys::fs::file_magic::bitcode: - return Object; - case sys::fs::file_magic::elf_relocatable: - case sys::fs::file_magic::macho_object: - case sys::fs::file_magic::coff_object: { - ErrorOr<std::unique_ptr<ObjectFile>> ObjFile = - ObjectFile::createObjectFile(Object, Type); - if (!ObjFile) - return ObjFile.getError(); - return findBitcodeInObject(*ObjFile->get()); - } - default: - return object_error::invalid_file_type; - } -} - -// Looks for function index in the given memory buffer. -// returns true if found, else false. -bool FunctionIndexObjectFile::hasFunctionSummaryInMemBuffer( - MemoryBufferRef Object, DiagnosticHandlerFunction DiagnosticHandler) { - ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); - if (!BCOrErr) - return false; - - return hasFunctionSummary(BCOrErr.get(), DiagnosticHandler); -} - -// Parse function index in the given memory buffer. -// Return new FunctionIndexObjectFile instance containing parsed -// function summary/index. -ErrorOr<std::unique_ptr<FunctionIndexObjectFile>> -FunctionIndexObjectFile::create(MemoryBufferRef Object, - DiagnosticHandlerFunction DiagnosticHandler, - bool IsLazy) { - std::unique_ptr<FunctionInfoIndex> Index; - - ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); - if (!BCOrErr) - return BCOrErr.getError(); - - ErrorOr<std::unique_ptr<FunctionInfoIndex>> IOrErr = getFunctionInfoIndex( - BCOrErr.get(), DiagnosticHandler, IsLazy); - - if (std::error_code EC = IOrErr.getError()) - return EC; - - Index = std::move(IOrErr.get()); - - return llvm::make_unique<FunctionIndexObjectFile>(Object, std::move(Index)); -} - -// Parse the function summary information for function with the -// given name out of the given buffer. Parsed information is -// stored on the index object saved in this object. -std::error_code FunctionIndexObjectFile::findFunctionSummaryInMemBuffer( - MemoryBufferRef Object, DiagnosticHandlerFunction DiagnosticHandler, - StringRef FunctionName) { - sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); - switch (Type) { - case sys::fs::file_magic::bitcode: { - return readFunctionSummary(Object, DiagnosticHandler, FunctionName, - std::move(Index)); - } - default: - return object_error::invalid_file_type; - } -} - -// Parse the function index out of an IR file and return the function -// index object if found, or nullptr if not. -ErrorOr<std::unique_ptr<FunctionInfoIndex>> -llvm::getFunctionIndexForFile(StringRef Path, - DiagnosticHandlerFunction DiagnosticHandler) { - ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = - MemoryBuffer::getFileOrSTDIN(Path); - std::error_code EC = FileOrErr.getError(); - if (EC) - return EC; - MemoryBufferRef BufferRef = (FileOrErr.get())->getMemBufferRef(); - ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr = - object::FunctionIndexObjectFile::create(BufferRef, DiagnosticHandler); - EC = ObjOrErr.getError(); - if (EC) - return EC; - - object::FunctionIndexObjectFile &Obj = **ObjOrErr; - return Obj.takeIndex(); -} diff --git a/gnu/llvm/lib/Object/Makefile b/gnu/llvm/lib/Object/Makefile deleted file mode 100644 index 79388dc97f1..00000000000 --- a/gnu/llvm/lib/Object/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/Object/Makefile ---------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMObject -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Option/Makefile b/gnu/llvm/lib/Option/Makefile deleted file mode 100644 index 255d0796e23..00000000000 --- a/gnu/llvm/lib/Option/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/Option/Makefile ---------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMOption -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Passes/Makefile b/gnu/llvm/lib/Passes/Makefile deleted file mode 100644 index 413dc5cf485..00000000000 --- a/gnu/llvm/lib/Passes/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/Passes/Makefile ---------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMPasses -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/ProfileData/CoverageMapping.cpp b/gnu/llvm/lib/ProfileData/CoverageMapping.cpp deleted file mode 100644 index f5d477bd139..00000000000 --- a/gnu/llvm/lib/ProfileData/CoverageMapping.cpp +++ /dev/null @@ -1,522 +0,0 @@ -//=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains support for clang's and llvm's instrumentation based -// code coverage. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ProfileData/CoverageMapping.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallBitVector.h" -#include "llvm/ProfileData/CoverageMappingReader.h" -#include "llvm/ProfileData/InstrProfReader.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Errc.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; -using namespace coverage; - -#define DEBUG_TYPE "coverage-mapping" - -Counter CounterExpressionBuilder::get(const CounterExpression &E) { - auto It = ExpressionIndices.find(E); - if (It != ExpressionIndices.end()) - return Counter::getExpression(It->second); - unsigned I = Expressions.size(); - Expressions.push_back(E); - ExpressionIndices[E] = I; - return Counter::getExpression(I); -} - -void CounterExpressionBuilder::extractTerms( - Counter C, int Sign, SmallVectorImpl<std::pair<unsigned, int>> &Terms) { - switch (C.getKind()) { - case Counter::Zero: - break; - case Counter::CounterValueReference: - Terms.push_back(std::make_pair(C.getCounterID(), Sign)); - break; - case Counter::Expression: - const auto &E = Expressions[C.getExpressionID()]; - extractTerms(E.LHS, Sign, Terms); - extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign, - Terms); - break; - } -} - -Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) { - // Gather constant terms. - llvm::SmallVector<std::pair<unsigned, int>, 32> Terms; - extractTerms(ExpressionTree, +1, Terms); - - // If there are no terms, this is just a zero. The algorithm below assumes at - // least one term. - if (Terms.size() == 0) - return Counter::getZero(); - - // Group the terms by counter ID. - std::sort(Terms.begin(), Terms.end(), - [](const std::pair<unsigned, int> &LHS, - const std::pair<unsigned, int> &RHS) { - return LHS.first < RHS.first; - }); - - // Combine terms by counter ID to eliminate counters that sum to zero. - auto Prev = Terms.begin(); - for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) { - if (I->first == Prev->first) { - Prev->second += I->second; - continue; - } - ++Prev; - *Prev = *I; - } - Terms.erase(++Prev, Terms.end()); - - Counter C; - // Create additions. We do this before subtractions to avoid constructs like - // ((0 - X) + Y), as opposed to (Y - X). - for (auto Term : Terms) { - if (Term.second <= 0) - continue; - for (int I = 0; I < Term.second; ++I) - if (C.isZero()) - C = Counter::getCounter(Term.first); - else - C = get(CounterExpression(CounterExpression::Add, C, - Counter::getCounter(Term.first))); - } - - // Create subtractions. - for (auto Term : Terms) { - if (Term.second >= 0) - continue; - for (int I = 0; I < -Term.second; ++I) - C = get(CounterExpression(CounterExpression::Subtract, C, - Counter::getCounter(Term.first))); - } - return C; -} - -Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) { - return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS))); -} - -Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) { - return simplify( - get(CounterExpression(CounterExpression::Subtract, LHS, RHS))); -} - -void CounterMappingContext::dump(const Counter &C, - llvm::raw_ostream &OS) const { - switch (C.getKind()) { - case Counter::Zero: - OS << '0'; - return; - case Counter::CounterValueReference: - OS << '#' << C.getCounterID(); - break; - case Counter::Expression: { - if (C.getExpressionID() >= Expressions.size()) - return; - const auto &E = Expressions[C.getExpressionID()]; - OS << '('; - dump(E.LHS, OS); - OS << (E.Kind == CounterExpression::Subtract ? " - " : " + "); - dump(E.RHS, OS); - OS << ')'; - break; - } - } - if (CounterValues.empty()) - return; - ErrorOr<int64_t> Value = evaluate(C); - if (!Value) - return; - OS << '[' << *Value << ']'; -} - -ErrorOr<int64_t> CounterMappingContext::evaluate(const Counter &C) const { - switch (C.getKind()) { - case Counter::Zero: - return 0; - case Counter::CounterValueReference: - if (C.getCounterID() >= CounterValues.size()) - return make_error_code(errc::argument_out_of_domain); - return CounterValues[C.getCounterID()]; - case Counter::Expression: { - if (C.getExpressionID() >= Expressions.size()) - return make_error_code(errc::argument_out_of_domain); - const auto &E = Expressions[C.getExpressionID()]; - ErrorOr<int64_t> LHS = evaluate(E.LHS); - if (!LHS) - return LHS; - ErrorOr<int64_t> RHS = evaluate(E.RHS); - if (!RHS) - return RHS; - return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS; - } - } - llvm_unreachable("Unhandled CounterKind"); -} - -void FunctionRecordIterator::skipOtherFiles() { - while (Current != Records.end() && !Filename.empty() && - Filename != Current->Filenames[0]) - ++Current; - if (Current == Records.end()) - *this = FunctionRecordIterator(); -} - -ErrorOr<std::unique_ptr<CoverageMapping>> -CoverageMapping::load(CoverageMappingReader &CoverageReader, - IndexedInstrProfReader &ProfileReader) { - auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping()); - - std::vector<uint64_t> Counts; - for (const auto &Record : CoverageReader) { - CounterMappingContext Ctx(Record.Expressions); - - Counts.clear(); - if (std::error_code EC = ProfileReader.getFunctionCounts( - Record.FunctionName, Record.FunctionHash, Counts)) { - if (EC == instrprof_error::hash_mismatch) { - Coverage->MismatchedFunctionCount++; - continue; - } else if (EC != instrprof_error::unknown_function) - return EC; - Counts.assign(Record.MappingRegions.size(), 0); - } - Ctx.setCounts(Counts); - - assert(!Record.MappingRegions.empty() && "Function has no regions"); - - StringRef OrigFuncName = Record.FunctionName; - if (!Record.Filenames.empty()) - OrigFuncName = - getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]); - FunctionRecord Function(OrigFuncName, Record.Filenames); - for (const auto &Region : Record.MappingRegions) { - ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(Region.Count); - if (!ExecutionCount) - break; - Function.pushRegion(Region, *ExecutionCount); - } - if (Function.CountedRegions.size() != Record.MappingRegions.size()) { - Coverage->MismatchedFunctionCount++; - continue; - } - - Coverage->Functions.push_back(std::move(Function)); - } - - return std::move(Coverage); -} - -ErrorOr<std::unique_ptr<CoverageMapping>> -CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename, - StringRef Arch) { - auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename); - if (std::error_code EC = CounterMappingBuff.getError()) - return EC; - auto CoverageReaderOrErr = - BinaryCoverageReader::create(CounterMappingBuff.get(), Arch); - if (std::error_code EC = CoverageReaderOrErr.getError()) - return EC; - auto CoverageReader = std::move(CoverageReaderOrErr.get()); - auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename); - if (auto EC = ProfileReaderOrErr.getError()) - return EC; - auto ProfileReader = std::move(ProfileReaderOrErr.get()); - return load(*CoverageReader, *ProfileReader); -} - -namespace { -/// \brief Distributes functions into instantiation sets. -/// -/// An instantiation set is a collection of functions that have the same source -/// code, ie, template functions specializations. -class FunctionInstantiationSetCollector { - typedef DenseMap<std::pair<unsigned, unsigned>, - std::vector<const FunctionRecord *>> MapT; - MapT InstantiatedFunctions; - -public: - void insert(const FunctionRecord &Function, unsigned FileID) { - auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end(); - while (I != E && I->FileID != FileID) - ++I; - assert(I != E && "function does not cover the given file"); - auto &Functions = InstantiatedFunctions[I->startLoc()]; - Functions.push_back(&Function); - } - - MapT::iterator begin() { return InstantiatedFunctions.begin(); } - - MapT::iterator end() { return InstantiatedFunctions.end(); } -}; - -class SegmentBuilder { - std::vector<CoverageSegment> Segments; - SmallVector<const CountedRegion *, 8> ActiveRegions; - - /// Start a segment with no count specified. - void startSegment(unsigned Line, unsigned Col) { - DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n"); - Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false); - } - - /// Start a segment with the given Region's count. - void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry, - const CountedRegion &Region) { - if (Segments.empty()) - Segments.emplace_back(Line, Col, IsRegionEntry); - CoverageSegment S = Segments.back(); - // Avoid creating empty regions. - if (S.Line != Line || S.Col != Col) { - Segments.emplace_back(Line, Col, IsRegionEntry); - S = Segments.back(); - } - DEBUG(dbgs() << "Segment at " << Line << ":" << Col); - // Set this region's count. - if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) { - DEBUG(dbgs() << " with count " << Region.ExecutionCount); - Segments.back().setCount(Region.ExecutionCount); - } - DEBUG(dbgs() << "\n"); - } - - /// Start a segment for the given region. - void startSegment(const CountedRegion &Region) { - startSegment(Region.LineStart, Region.ColumnStart, true, Region); - } - - /// Pop the top region off of the active stack, starting a new segment with - /// the containing Region's count. - void popRegion() { - const CountedRegion *Active = ActiveRegions.back(); - unsigned Line = Active->LineEnd, Col = Active->ColumnEnd; - ActiveRegions.pop_back(); - if (ActiveRegions.empty()) - startSegment(Line, Col); - else - startSegment(Line, Col, false, *ActiveRegions.back()); - } - -public: - /// Build a list of CoverageSegments from a sorted list of Regions. - std::vector<CoverageSegment> buildSegments(ArrayRef<CountedRegion> Regions) { - const CountedRegion *PrevRegion = nullptr; - for (const auto &Region : Regions) { - // Pop any regions that end before this one starts. - while (!ActiveRegions.empty() && - ActiveRegions.back()->endLoc() <= Region.startLoc()) - popRegion(); - if (PrevRegion && PrevRegion->startLoc() == Region.startLoc() && - PrevRegion->endLoc() == Region.endLoc()) { - if (Region.Kind == coverage::CounterMappingRegion::CodeRegion) - Segments.back().addCount(Region.ExecutionCount); - } else { - // Add this region to the stack. - ActiveRegions.push_back(&Region); - startSegment(Region); - } - PrevRegion = &Region; - } - // Pop any regions that are left in the stack. - while (!ActiveRegions.empty()) - popRegion(); - return Segments; - } -}; -} - -std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const { - std::vector<StringRef> Filenames; - for (const auto &Function : getCoveredFunctions()) - Filenames.insert(Filenames.end(), Function.Filenames.begin(), - Function.Filenames.end()); - std::sort(Filenames.begin(), Filenames.end()); - auto Last = std::unique(Filenames.begin(), Filenames.end()); - Filenames.erase(Last, Filenames.end()); - return Filenames; -} - -static SmallBitVector gatherFileIDs(StringRef SourceFile, - const FunctionRecord &Function) { - SmallBitVector FilenameEquivalence(Function.Filenames.size(), false); - for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) - if (SourceFile == Function.Filenames[I]) - FilenameEquivalence[I] = true; - return FilenameEquivalence; -} - -static Optional<unsigned> findMainViewFileID(StringRef SourceFile, - const FunctionRecord &Function) { - SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true); - SmallBitVector FilenameEquivalence = gatherFileIDs(SourceFile, Function); - for (const auto &CR : Function.CountedRegions) - if (CR.Kind == CounterMappingRegion::ExpansionRegion && - FilenameEquivalence[CR.FileID]) - IsNotExpandedFile[CR.ExpandedFileID] = false; - IsNotExpandedFile &= FilenameEquivalence; - int I = IsNotExpandedFile.find_first(); - if (I == -1) - return None; - return I; -} - -static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) { - SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true); - for (const auto &CR : Function.CountedRegions) - if (CR.Kind == CounterMappingRegion::ExpansionRegion) - IsNotExpandedFile[CR.ExpandedFileID] = false; - int I = IsNotExpandedFile.find_first(); - if (I == -1) - return None; - return I; -} - -/// Sort a nested sequence of regions from a single file. -template <class It> static void sortNestedRegions(It First, It Last) { - std::sort(First, Last, - [](const CountedRegion &LHS, const CountedRegion &RHS) { - if (LHS.startLoc() == RHS.startLoc()) - // When LHS completely contains RHS, we sort LHS first. - return RHS.endLoc() < LHS.endLoc(); - return LHS.startLoc() < RHS.startLoc(); - }); -} - -static bool isExpansion(const CountedRegion &R, unsigned FileID) { - return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID; -} - -CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) { - CoverageData FileCoverage(Filename); - std::vector<coverage::CountedRegion> Regions; - - for (const auto &Function : Functions) { - auto MainFileID = findMainViewFileID(Filename, Function); - if (!MainFileID) - continue; - auto FileIDs = gatherFileIDs(Filename, Function); - for (const auto &CR : Function.CountedRegions) - if (FileIDs.test(CR.FileID)) { - Regions.push_back(CR); - if (isExpansion(CR, *MainFileID)) - FileCoverage.Expansions.emplace_back(CR, Function); - } - } - - sortNestedRegions(Regions.begin(), Regions.end()); - DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n"); - FileCoverage.Segments = SegmentBuilder().buildSegments(Regions); - - return FileCoverage; -} - -std::vector<const FunctionRecord *> -CoverageMapping::getInstantiations(StringRef Filename) { - FunctionInstantiationSetCollector InstantiationSetCollector; - for (const auto &Function : Functions) { - auto MainFileID = findMainViewFileID(Filename, Function); - if (!MainFileID) - continue; - InstantiationSetCollector.insert(Function, *MainFileID); - } - - std::vector<const FunctionRecord *> Result; - for (const auto &InstantiationSet : InstantiationSetCollector) { - if (InstantiationSet.second.size() < 2) - continue; - Result.insert(Result.end(), InstantiationSet.second.begin(), - InstantiationSet.second.end()); - } - return Result; -} - -CoverageData -CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) { - auto MainFileID = findMainViewFileID(Function); - if (!MainFileID) - return CoverageData(); - - CoverageData FunctionCoverage(Function.Filenames[*MainFileID]); - std::vector<coverage::CountedRegion> Regions; - for (const auto &CR : Function.CountedRegions) - if (CR.FileID == *MainFileID) { - Regions.push_back(CR); - if (isExpansion(CR, *MainFileID)) - FunctionCoverage.Expansions.emplace_back(CR, Function); - } - - sortNestedRegions(Regions.begin(), Regions.end()); - DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n"); - FunctionCoverage.Segments = SegmentBuilder().buildSegments(Regions); - - return FunctionCoverage; -} - -CoverageData -CoverageMapping::getCoverageForExpansion(const ExpansionRecord &Expansion) { - CoverageData ExpansionCoverage( - Expansion.Function.Filenames[Expansion.FileID]); - std::vector<coverage::CountedRegion> Regions; - for (const auto &CR : Expansion.Function.CountedRegions) - if (CR.FileID == Expansion.FileID) { - Regions.push_back(CR); - if (isExpansion(CR, Expansion.FileID)) - ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function); - } - - sortNestedRegions(Regions.begin(), Regions.end()); - DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID - << "\n"); - ExpansionCoverage.Segments = SegmentBuilder().buildSegments(Regions); - - return ExpansionCoverage; -} - -namespace { -class CoverageMappingErrorCategoryType : public std::error_category { - const char *name() const LLVM_NOEXCEPT override { return "llvm.coveragemap"; } - std::string message(int IE) const override { - auto E = static_cast<coveragemap_error>(IE); - switch (E) { - case coveragemap_error::success: - return "Success"; - case coveragemap_error::eof: - return "End of File"; - case coveragemap_error::no_data_found: - return "No coverage data found"; - case coveragemap_error::unsupported_version: - return "Unsupported coverage format version"; - case coveragemap_error::truncated: - return "Truncated coverage data"; - case coveragemap_error::malformed: - return "Malformed coverage data"; - } - llvm_unreachable("A value of coveragemap_error has no message."); - } -}; -} - -static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory; - -const std::error_category &llvm::coverage::coveragemap_category() { - return *ErrorCategory; -} diff --git a/gnu/llvm/lib/ProfileData/CoverageMappingReader.cpp b/gnu/llvm/lib/ProfileData/CoverageMappingReader.cpp deleted file mode 100644 index 89e1cf42c57..00000000000 --- a/gnu/llvm/lib/ProfileData/CoverageMappingReader.cpp +++ /dev/null @@ -1,547 +0,0 @@ -//=-- CoverageMappingReader.cpp - Code coverage mapping reader ----*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains support for reading coverage mapping data for -// instrumentation based coverage. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ProfileData/CoverageMappingReader.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/Object/MachOUniversal.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; -using namespace coverage; -using namespace object; - -#define DEBUG_TYPE "coverage-mapping" - -void CoverageMappingIterator::increment() { - // Check if all the records were read or if an error occurred while reading - // the next record. - if (Reader->readNextRecord(Record)) - *this = CoverageMappingIterator(); -} - -std::error_code RawCoverageReader::readULEB128(uint64_t &Result) { - if (Data.size() < 1) - return coveragemap_error::truncated; - unsigned N = 0; - Result = decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); - if (N > Data.size()) - return coveragemap_error::malformed; - Data = Data.substr(N); - return std::error_code(); -} - -std::error_code RawCoverageReader::readIntMax(uint64_t &Result, - uint64_t MaxPlus1) { - if (auto Err = readULEB128(Result)) - return Err; - if (Result >= MaxPlus1) - return coveragemap_error::malformed; - return std::error_code(); -} - -std::error_code RawCoverageReader::readSize(uint64_t &Result) { - if (auto Err = readULEB128(Result)) - return Err; - // Sanity check the number. - if (Result > Data.size()) - return coveragemap_error::malformed; - return std::error_code(); -} - -std::error_code RawCoverageReader::readString(StringRef &Result) { - uint64_t Length; - if (auto Err = readSize(Length)) - return Err; - Result = Data.substr(0, Length); - Data = Data.substr(Length); - return std::error_code(); -} - -std::error_code RawCoverageFilenamesReader::read() { - uint64_t NumFilenames; - if (auto Err = readSize(NumFilenames)) - return Err; - for (size_t I = 0; I < NumFilenames; ++I) { - StringRef Filename; - if (auto Err = readString(Filename)) - return Err; - Filenames.push_back(Filename); - } - return std::error_code(); -} - -std::error_code RawCoverageMappingReader::decodeCounter(unsigned Value, - Counter &C) { - auto Tag = Value & Counter::EncodingTagMask; - switch (Tag) { - case Counter::Zero: - C = Counter::getZero(); - return std::error_code(); - case Counter::CounterValueReference: - C = Counter::getCounter(Value >> Counter::EncodingTagBits); - return std::error_code(); - default: - break; - } - Tag -= Counter::Expression; - switch (Tag) { - case CounterExpression::Subtract: - case CounterExpression::Add: { - auto ID = Value >> Counter::EncodingTagBits; - if (ID >= Expressions.size()) - return coveragemap_error::malformed; - Expressions[ID].Kind = CounterExpression::ExprKind(Tag); - C = Counter::getExpression(ID); - break; - } - default: - return coveragemap_error::malformed; - } - return std::error_code(); -} - -std::error_code RawCoverageMappingReader::readCounter(Counter &C) { - uint64_t EncodedCounter; - if (auto Err = - readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max())) - return Err; - if (auto Err = decodeCounter(EncodedCounter, C)) - return Err; - return std::error_code(); -} - -static const unsigned EncodingExpansionRegionBit = 1 - << Counter::EncodingTagBits; - -/// \brief Read the sub-array of regions for the given inferred file id. -/// \param NumFileIDs the number of file ids that are defined for this -/// function. -std::error_code RawCoverageMappingReader::readMappingRegionsSubArray( - std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID, - size_t NumFileIDs) { - uint64_t NumRegions; - if (auto Err = readSize(NumRegions)) - return Err; - unsigned LineStart = 0; - for (size_t I = 0; I < NumRegions; ++I) { - Counter C; - CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; - - // Read the combined counter + region kind. - uint64_t EncodedCounterAndRegion; - if (auto Err = readIntMax(EncodedCounterAndRegion, - std::numeric_limits<unsigned>::max())) - return Err; - unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; - uint64_t ExpandedFileID = 0; - if (Tag != Counter::Zero) { - if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) - return Err; - } else { - // Is it an expansion region? - if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { - Kind = CounterMappingRegion::ExpansionRegion; - ExpandedFileID = EncodedCounterAndRegion >> - Counter::EncodingCounterTagAndExpansionRegionTagBits; - if (ExpandedFileID >= NumFileIDs) - return coveragemap_error::malformed; - } else { - switch (EncodedCounterAndRegion >> - Counter::EncodingCounterTagAndExpansionRegionTagBits) { - case CounterMappingRegion::CodeRegion: - // Don't do anything when we have a code region with a zero counter. - break; - case CounterMappingRegion::SkippedRegion: - Kind = CounterMappingRegion::SkippedRegion; - break; - default: - return coveragemap_error::malformed; - } - } - } - - // Read the source range. - uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd; - if (auto Err = - readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max())) - return Err; - if (auto Err = readULEB128(ColumnStart)) - return Err; - if (ColumnStart > std::numeric_limits<unsigned>::max()) - return coveragemap_error::malformed; - if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) - return Err; - if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) - return Err; - LineStart += LineStartDelta; - // Adjust the column locations for the empty regions that are supposed to - // cover whole lines. Those regions should be encoded with the - // column range (1 -> std::numeric_limits<unsigned>::max()), but because - // the encoded std::numeric_limits<unsigned>::max() is several bytes long, - // we set the column range to (0 -> 0) to ensure that the column start and - // column end take up one byte each. - // The std::numeric_limits<unsigned>::max() is used to represent a column - // position at the end of the line without knowing the length of that line. - if (ColumnStart == 0 && ColumnEnd == 0) { - ColumnStart = 1; - ColumnEnd = std::numeric_limits<unsigned>::max(); - } - - DEBUG({ - dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" - << ColumnStart << " -> " << (LineStart + NumLines) << ":" - << ColumnEnd << ", "; - if (Kind == CounterMappingRegion::ExpansionRegion) - dbgs() << "Expands to file " << ExpandedFileID; - else - CounterMappingContext(Expressions).dump(C, dbgs()); - dbgs() << "\n"; - }); - - MappingRegions.push_back(CounterMappingRegion( - C, InferredFileID, ExpandedFileID, LineStart, ColumnStart, - LineStart + NumLines, ColumnEnd, Kind)); - } - return std::error_code(); -} - -std::error_code RawCoverageMappingReader::read() { - - // Read the virtual file mapping. - llvm::SmallVector<unsigned, 8> VirtualFileMapping; - uint64_t NumFileMappings; - if (auto Err = readSize(NumFileMappings)) - return Err; - for (size_t I = 0; I < NumFileMappings; ++I) { - uint64_t FilenameIndex; - if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) - return Err; - VirtualFileMapping.push_back(FilenameIndex); - } - - // Construct the files using unique filenames and virtual file mapping. - for (auto I : VirtualFileMapping) { - Filenames.push_back(TranslationUnitFilenames[I]); - } - - // Read the expressions. - uint64_t NumExpressions; - if (auto Err = readSize(NumExpressions)) - return Err; - // Create an array of dummy expressions that get the proper counters - // when the expressions are read, and the proper kinds when the counters - // are decoded. - Expressions.resize( - NumExpressions, - CounterExpression(CounterExpression::Subtract, Counter(), Counter())); - for (size_t I = 0; I < NumExpressions; ++I) { - if (auto Err = readCounter(Expressions[I].LHS)) - return Err; - if (auto Err = readCounter(Expressions[I].RHS)) - return Err; - } - - // Read the mapping regions sub-arrays. - for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); - InferredFileID < S; ++InferredFileID) { - if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, - VirtualFileMapping.size())) - return Err; - } - - // Set the counters for the expansion regions. - // i.e. Counter of expansion region = counter of the first region - // from the expanded file. - // Perform multiple passes to correctly propagate the counters through - // all the nested expansion regions. - SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; - FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); - for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { - for (auto &R : MappingRegions) { - if (R.Kind != CounterMappingRegion::ExpansionRegion) - continue; - assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); - FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; - } - for (auto &R : MappingRegions) { - if (FileIDExpansionRegionMapping[R.FileID]) { - FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; - FileIDExpansionRegionMapping[R.FileID] = nullptr; - } - } - } - - return std::error_code(); -} - -std::error_code InstrProfSymtab::create(SectionRef &Section) { - if (auto Err = Section.getContents(Data)) - return Err; - Address = Section.getAddress(); - return std::error_code(); -} - -StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { - if (Pointer < Address) - return StringRef(); - auto Offset = Pointer - Address; - if (Offset + Size > Data.size()) - return StringRef(); - return Data.substr(Pointer - Address, Size); -} - -template <typename T, support::endianness Endian> -static std::error_code readCoverageMappingData( - InstrProfSymtab &ProfileNames, StringRef Data, - std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, - std::vector<StringRef> &Filenames) { - using namespace support; - llvm::DenseSet<T> UniqueFunctionMappingData; - - // Read the records in the coverage data section. - for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { - if (Buf + sizeof(CovMapHeader) > End) - return coveragemap_error::malformed; - auto CovHeader = reinterpret_cast<const coverage::CovMapHeader *>(Buf); - uint32_t NRecords = CovHeader->getNRecords<Endian>(); - uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); - uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); - uint32_t Version = CovHeader->getVersion<Endian>(); - Buf = reinterpret_cast<const char *>(++CovHeader); - - if (Version > coverage::CoverageMappingCurrentVersion) - return coveragemap_error::unsupported_version; - - // Skip past the function records, saving the start and end for later. - const char *FunBuf = Buf; - Buf += NRecords * sizeof(coverage::CovMapFunctionRecord<T>); - const char *FunEnd = Buf; - - // Get the filenames. - if (Buf + FilenamesSize > End) - return coveragemap_error::malformed; - size_t FilenamesBegin = Filenames.size(); - RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames); - if (auto Err = Reader.read()) - return Err; - Buf += FilenamesSize; - - // We'll read the coverage mapping records in the loop below. - const char *CovBuf = Buf; - Buf += CoverageSize; - const char *CovEnd = Buf; - - if (Buf > End) - return coveragemap_error::malformed; - // Each coverage map has an alignment of 8, so we need to adjust alignment - // before reading the next map. - Buf += alignmentAdjustment(Buf, 8); - - auto CFR = - reinterpret_cast<const coverage::CovMapFunctionRecord<T> *>(FunBuf); - while ((const char *)CFR < FunEnd) { - // Read the function information - uint32_t DataSize = CFR->template getDataSize<Endian>(); - uint64_t FuncHash = CFR->template getFuncHash<Endian>(); - - // Now use that to read the coverage data. - if (CovBuf + DataSize > CovEnd) - return coveragemap_error::malformed; - auto Mapping = StringRef(CovBuf, DataSize); - CovBuf += DataSize; - - // Ignore this record if we already have a record that points to the same - // function name. This is useful to ignore the redundant records for the - // functions with ODR linkage. - T NameRef = CFR->template getFuncNameRef<Endian>(); - if (!UniqueFunctionMappingData.insert(NameRef).second) - continue; - - StringRef FuncName; - if (std::error_code EC = - CFR->template getFuncName<Endian>(ProfileNames, FuncName)) - return EC; - Records.push_back(BinaryCoverageReader::ProfileMappingRecord( - CoverageMappingVersion(Version), FuncName, FuncHash, Mapping, - FilenamesBegin, Filenames.size() - FilenamesBegin)); - CFR++; - } - } - - return std::error_code(); -} - -static const char *TestingFormatMagic = "llvmcovmtestdata"; - -static std::error_code loadTestingFormat(StringRef Data, - InstrProfSymtab &ProfileNames, - StringRef &CoverageMapping, - uint8_t &BytesInAddress, - support::endianness &Endian) { - BytesInAddress = 8; - Endian = support::endianness::little; - - Data = Data.substr(StringRef(TestingFormatMagic).size()); - if (Data.size() < 1) - return coveragemap_error::truncated; - unsigned N = 0; - auto ProfileNamesSize = - decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); - if (N > Data.size()) - return coveragemap_error::malformed; - Data = Data.substr(N); - if (Data.size() < 1) - return coveragemap_error::truncated; - N = 0; - uint64_t Address = - decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); - if (N > Data.size()) - return coveragemap_error::malformed; - Data = Data.substr(N); - if (Data.size() < ProfileNamesSize) - return coveragemap_error::malformed; - ProfileNames.create(Data.substr(0, ProfileNamesSize), Address); - CoverageMapping = Data.substr(ProfileNamesSize); - return std::error_code(); -} - -static ErrorOr<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) { - StringRef FoundName; - for (const auto &Section : OF.sections()) { - if (auto EC = Section.getName(FoundName)) - return EC; - if (FoundName == Name) - return Section; - } - return coveragemap_error::no_data_found; -} - -static std::error_code -loadBinaryFormat(MemoryBufferRef ObjectBuffer, InstrProfSymtab &ProfileNames, - StringRef &CoverageMapping, uint8_t &BytesInAddress, - support::endianness &Endian, StringRef Arch) { - auto BinOrErr = object::createBinary(ObjectBuffer); - if (std::error_code EC = BinOrErr.getError()) - return EC; - auto Bin = std::move(BinOrErr.get()); - std::unique_ptr<ObjectFile> OF; - if (auto *Universal = dyn_cast<object::MachOUniversalBinary>(Bin.get())) { - // If we have a universal binary, try to look up the object for the - // appropriate architecture. - auto ObjectFileOrErr = Universal->getObjectForArch(Arch); - if (std::error_code EC = ObjectFileOrErr.getError()) - return EC; - OF = std::move(ObjectFileOrErr.get()); - } else if (isa<object::ObjectFile>(Bin.get())) { - // For any other object file, upcast and take ownership. - OF.reset(cast<object::ObjectFile>(Bin.release())); - // If we've asked for a particular arch, make sure they match. - if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) - return object_error::arch_not_found; - } else - // We can only handle object files. - return coveragemap_error::malformed; - - // The coverage uses native pointer sizes for the object it's written in. - BytesInAddress = OF->getBytesInAddress(); - Endian = OF->isLittleEndian() ? support::endianness::little - : support::endianness::big; - - // Look for the sections that we are interested in. - auto NamesSection = lookupSection(*OF, getInstrProfNameSectionName(false)); - if (auto EC = NamesSection.getError()) - return EC; - auto CoverageSection = - lookupSection(*OF, getInstrProfCoverageSectionName(false)); - if (auto EC = CoverageSection.getError()) - return EC; - - // Get the contents of the given sections. - if (std::error_code EC = CoverageSection->getContents(CoverageMapping)) - return EC; - if (std::error_code EC = ProfileNames.create(*NamesSection)) - return EC; - - return std::error_code(); -} - -ErrorOr<std::unique_ptr<BinaryCoverageReader>> -BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer, - StringRef Arch) { - std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader()); - - InstrProfSymtab ProfileNames; - StringRef Coverage; - uint8_t BytesInAddress; - support::endianness Endian; - std::error_code EC; - if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic)) - // This is a special format used for testing. - EC = loadTestingFormat(ObjectBuffer->getBuffer(), ProfileNames, Coverage, - BytesInAddress, Endian); - else - EC = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), ProfileNames, - Coverage, BytesInAddress, Endian, Arch); - if (EC) - return EC; - - if (BytesInAddress == 4 && Endian == support::endianness::little) - EC = readCoverageMappingData<uint32_t, support::endianness::little>( - ProfileNames, Coverage, Reader->MappingRecords, Reader->Filenames); - else if (BytesInAddress == 4 && Endian == support::endianness::big) - EC = readCoverageMappingData<uint32_t, support::endianness::big>( - ProfileNames, Coverage, Reader->MappingRecords, Reader->Filenames); - else if (BytesInAddress == 8 && Endian == support::endianness::little) - EC = readCoverageMappingData<uint64_t, support::endianness::little>( - ProfileNames, Coverage, Reader->MappingRecords, Reader->Filenames); - else if (BytesInAddress == 8 && Endian == support::endianness::big) - EC = readCoverageMappingData<uint64_t, support::endianness::big>( - ProfileNames, Coverage, Reader->MappingRecords, Reader->Filenames); - else - return coveragemap_error::malformed; - if (EC) - return EC; - return std::move(Reader); -} - -std::error_code -BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { - if (CurrentRecord >= MappingRecords.size()) - return coveragemap_error::eof; - - FunctionsFilenames.clear(); - Expressions.clear(); - MappingRegions.clear(); - auto &R = MappingRecords[CurrentRecord]; - RawCoverageMappingReader Reader( - R.CoverageMapping, - makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize), - FunctionsFilenames, Expressions, MappingRegions); - if (auto Err = Reader.read()) - return Err; - - Record.FunctionName = R.FunctionName; - Record.FunctionHash = R.FunctionHash; - Record.Filenames = FunctionsFilenames; - Record.Expressions = Expressions; - Record.MappingRegions = MappingRegions; - - ++CurrentRecord; - return std::error_code(); -} diff --git a/gnu/llvm/lib/ProfileData/CoverageMappingWriter.cpp b/gnu/llvm/lib/ProfileData/CoverageMappingWriter.cpp deleted file mode 100644 index d90d2f56515..00000000000 --- a/gnu/llvm/lib/ProfileData/CoverageMappingWriter.cpp +++ /dev/null @@ -1,183 +0,0 @@ -//=-- CoverageMappingWriter.cpp - Code coverage mapping writer -------------=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains support for writing coverage mapping data for -// instrumentation based coverage. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ProfileData/CoverageMappingWriter.h" -#include "llvm/Support/LEB128.h" - -using namespace llvm; -using namespace coverage; - -void CoverageFilenamesSectionWriter::write(raw_ostream &OS) { - encodeULEB128(Filenames.size(), OS); - for (const auto &Filename : Filenames) { - encodeULEB128(Filename.size(), OS); - OS << Filename; - } -} - -namespace { -/// \brief Gather only the expressions that are used by the mapping -/// regions in this function. -class CounterExpressionsMinimizer { - ArrayRef<CounterExpression> Expressions; - llvm::SmallVector<CounterExpression, 16> UsedExpressions; - std::vector<unsigned> AdjustedExpressionIDs; - -public: - void mark(Counter C) { - if (!C.isExpression()) - return; - unsigned ID = C.getExpressionID(); - AdjustedExpressionIDs[ID] = 1; - mark(Expressions[ID].LHS); - mark(Expressions[ID].RHS); - } - - void gatherUsed(Counter C) { - if (!C.isExpression() || !AdjustedExpressionIDs[C.getExpressionID()]) - return; - AdjustedExpressionIDs[C.getExpressionID()] = UsedExpressions.size(); - const auto &E = Expressions[C.getExpressionID()]; - UsedExpressions.push_back(E); - gatherUsed(E.LHS); - gatherUsed(E.RHS); - } - - CounterExpressionsMinimizer(ArrayRef<CounterExpression> Expressions, - ArrayRef<CounterMappingRegion> MappingRegions) - : Expressions(Expressions) { - AdjustedExpressionIDs.resize(Expressions.size(), 0); - for (const auto &I : MappingRegions) - mark(I.Count); - for (const auto &I : MappingRegions) - gatherUsed(I.Count); - } - - ArrayRef<CounterExpression> getExpressions() const { return UsedExpressions; } - - /// \brief Adjust the given counter to correctly transition from the old - /// expression ids to the new expression ids. - Counter adjust(Counter C) const { - if (C.isExpression()) - C = Counter::getExpression(AdjustedExpressionIDs[C.getExpressionID()]); - return C; - } -}; -} - -/// \brief Encode the counter. -/// -/// The encoding uses the following format: -/// Low 2 bits - Tag: -/// Counter::Zero(0) - A Counter with kind Counter::Zero -/// Counter::CounterValueReference(1) - A counter with kind -/// Counter::CounterValueReference -/// Counter::Expression(2) + CounterExpression::Subtract(0) - -/// A counter with kind Counter::Expression and an expression -/// with kind CounterExpression::Subtract -/// Counter::Expression(2) + CounterExpression::Add(1) - -/// A counter with kind Counter::Expression and an expression -/// with kind CounterExpression::Add -/// Remaining bits - Counter/Expression ID. -static unsigned encodeCounter(ArrayRef<CounterExpression> Expressions, - Counter C) { - unsigned Tag = unsigned(C.getKind()); - if (C.isExpression()) - Tag += Expressions[C.getExpressionID()].Kind; - unsigned ID = C.getCounterID(); - assert(ID <= - (std::numeric_limits<unsigned>::max() >> Counter::EncodingTagBits)); - return Tag | (ID << Counter::EncodingTagBits); -} - -static void writeCounter(ArrayRef<CounterExpression> Expressions, Counter C, - raw_ostream &OS) { - encodeULEB128(encodeCounter(Expressions, C), OS); -} - -void CoverageMappingWriter::write(raw_ostream &OS) { - // Sort the regions in an ascending order by the file id and the starting - // location. - std::stable_sort(MappingRegions.begin(), MappingRegions.end()); - - // Write out the fileid -> filename mapping. - encodeULEB128(VirtualFileMapping.size(), OS); - for (const auto &FileID : VirtualFileMapping) - encodeULEB128(FileID, OS); - - // Write out the expressions. - CounterExpressionsMinimizer Minimizer(Expressions, MappingRegions); - auto MinExpressions = Minimizer.getExpressions(); - encodeULEB128(MinExpressions.size(), OS); - for (const auto &E : MinExpressions) { - writeCounter(MinExpressions, Minimizer.adjust(E.LHS), OS); - writeCounter(MinExpressions, Minimizer.adjust(E.RHS), OS); - } - - // Write out the mapping regions. - // Split the regions into subarrays where each region in a - // subarray has a fileID which is the index of that subarray. - unsigned PrevLineStart = 0; - unsigned CurrentFileID = ~0U; - for (auto I = MappingRegions.begin(), E = MappingRegions.end(); I != E; ++I) { - if (I->FileID != CurrentFileID) { - // Ensure that all file ids have at least one mapping region. - assert(I->FileID == (CurrentFileID + 1)); - // Find the number of regions with this file id. - unsigned RegionCount = 1; - for (auto J = I + 1; J != E && I->FileID == J->FileID; ++J) - ++RegionCount; - // Start a new region sub-array. - encodeULEB128(RegionCount, OS); - - CurrentFileID = I->FileID; - PrevLineStart = 0; - } - Counter Count = Minimizer.adjust(I->Count); - switch (I->Kind) { - case CounterMappingRegion::CodeRegion: - writeCounter(MinExpressions, Count, OS); - break; - case CounterMappingRegion::ExpansionRegion: { - assert(Count.isZero()); - assert(I->ExpandedFileID <= - (std::numeric_limits<unsigned>::max() >> - Counter::EncodingCounterTagAndExpansionRegionTagBits)); - // Mark an expansion region with a set bit that follows the counter tag, - // and pack the expanded file id into the remaining bits. - unsigned EncodedTagExpandedFileID = - (1 << Counter::EncodingTagBits) | - (I->ExpandedFileID - << Counter::EncodingCounterTagAndExpansionRegionTagBits); - encodeULEB128(EncodedTagExpandedFileID, OS); - break; - } - case CounterMappingRegion::SkippedRegion: - assert(Count.isZero()); - encodeULEB128(unsigned(I->Kind) - << Counter::EncodingCounterTagAndExpansionRegionTagBits, - OS); - break; - } - assert(I->LineStart >= PrevLineStart); - encodeULEB128(I->LineStart - PrevLineStart, OS); - encodeULEB128(I->ColumnStart, OS); - assert(I->LineEnd >= I->LineStart); - encodeULEB128(I->LineEnd - I->LineStart, OS); - encodeULEB128(I->ColumnEnd, OS); - PrevLineStart = I->LineStart; - } - // Ensure that all file ids have at least one mapping region. - assert(CurrentFileID == (VirtualFileMapping.size() - 1)); -} diff --git a/gnu/llvm/lib/ProfileData/Makefile b/gnu/llvm/lib/ProfileData/Makefile deleted file mode 100644 index 26743612d3d..00000000000 --- a/gnu/llvm/lib/ProfileData/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/ProfileData/Makefile ----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMProfileData -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Support/Makefile b/gnu/llvm/lib/Support/Makefile deleted file mode 100644 index 39426aaaace..00000000000 --- a/gnu/llvm/lib/Support/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -##===- lib/Support/Makefile --------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMSupport -BUILD_ARCHIVE = 1 - -EXTRA_DIST = Unix Win32 README.txt - -include $(LEVEL)/Makefile.common - -CompileCommonOpts := $(filter-out -pedantic,$(CompileCommonOpts)) -CompileCommonOpts := $(filter-out -Wno-long-long,$(CompileCommonOpts)) - -ifdef LLVM_VERSION_INFO -CompileCommonOpts += -DLLVM_VERSION_INFO='"$(LLVM_VERSION_INFO)"' -endif diff --git a/gnu/llvm/lib/TableGen/Makefile b/gnu/llvm/lib/TableGen/Makefile deleted file mode 100644 index 345db3465cf..00000000000 --- a/gnu/llvm/lib/TableGen/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/TableGen/Makefile -------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMTableGen -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/TableGen/module.modulemap b/gnu/llvm/lib/TableGen/module.modulemap deleted file mode 100644 index 8dac0a22c14..00000000000 --- a/gnu/llvm/lib/TableGen/module.modulemap +++ /dev/null @@ -1 +0,0 @@ -module TableGen { requires cplusplus umbrella "." module * { export * } } diff --git a/gnu/llvm/lib/Target/AArch64/AsmParser/Makefile b/gnu/llvm/lib/Target/AArch64/AsmParser/Makefile deleted file mode 100644 index 00268c76f8e..00000000000 --- a/gnu/llvm/lib/Target/AArch64/AsmParser/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/AArch64/AsmParser/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMAArch64AsmParser - -# Hack: we need to include 'main' ARM target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AArch64/Disassembler/Makefile b/gnu/llvm/lib/Target/AArch64/Disassembler/Makefile deleted file mode 100644 index 741bb817a63..00000000000 --- a/gnu/llvm/lib/Target/AArch64/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/AArch64/Disassembler/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMAArch64Disassembler - -# Hack: we need to include 'main' arm target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AArch64/InstPrinter/Makefile b/gnu/llvm/lib/Target/AArch64/InstPrinter/Makefile deleted file mode 100644 index b17e8d08011..00000000000 --- a/gnu/llvm/lib/Target/AArch64/InstPrinter/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/AArch64/AsmPrinter/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMAArch64AsmPrinter - -# Hack: we need to include 'main' arm target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AArch64/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/AArch64/MCTargetDesc/Makefile deleted file mode 100644 index 5779ac5ac60..00000000000 --- a/gnu/llvm/lib/Target/AArch64/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/AArch64/TargetDesc/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMAArch64Desc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AArch64/Makefile b/gnu/llvm/lib/Target/AArch64/Makefile deleted file mode 100644 index f356c585041..00000000000 --- a/gnu/llvm/lib/Target/AArch64/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -##===- lib/Target/AArch64/Makefile -------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMAArch64CodeGen -TARGET = AArch64 - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = AArch64GenRegisterInfo.inc AArch64GenInstrInfo.inc \ - AArch64GenAsmWriter.inc AArch64GenAsmWriter1.inc \ - AArch64GenDAGISel.inc \ - AArch64GenCallingConv.inc AArch64GenAsmMatcher.inc \ - AArch64GenSubtargetInfo.inc AArch64GenMCCodeEmitter.inc \ - AArch64GenFastISel.inc AArch64GenDisassemblerTables.inc \ - AArch64GenMCPseudoLowering.inc - -DIRS = TargetInfo InstPrinter AsmParser Disassembler MCTargetDesc Utils - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AArch64/TargetInfo/Makefile b/gnu/llvm/lib/Target/AArch64/TargetInfo/Makefile deleted file mode 100644 index 9dc9aa4bccf..00000000000 --- a/gnu/llvm/lib/Target/AArch64/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/AArch64/TargetInfo/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMAArch64Info - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AArch64/Utils/Makefile b/gnu/llvm/lib/Target/AArch64/Utils/Makefile deleted file mode 100644 index 0b80f82f2b9..00000000000 --- a/gnu/llvm/lib/Target/AArch64/Utils/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/AArch64/Utils/Makefile -------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMAArch64Utils - -# Hack: we need to include 'main' AArch64 target directory to grab private -# headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AMDGPU/AMDGPUDiagnosticInfoUnsupported.cpp b/gnu/llvm/lib/Target/AMDGPU/AMDGPUDiagnosticInfoUnsupported.cpp deleted file mode 100644 index 2f6b3022dd6..00000000000 --- a/gnu/llvm/lib/Target/AMDGPU/AMDGPUDiagnosticInfoUnsupported.cpp +++ /dev/null @@ -1,26 +0,0 @@ -//===-- AMDGPUDiagnosticInfoUnsupported.cpp -------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "AMDGPUDiagnosticInfoUnsupported.h" - -using namespace llvm; - -DiagnosticInfoUnsupported::DiagnosticInfoUnsupported( - const Function &Fn, - const Twine &Desc, - DiagnosticSeverity Severity) - : DiagnosticInfo(getKindID(), Severity), - Description(Desc), - Fn(Fn) { } - -int DiagnosticInfoUnsupported::KindID = 0; - -void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const { - DP << "unsupported " << getDescription() << " in " << Fn.getName(); -} diff --git a/gnu/llvm/lib/Target/AMDGPU/AMDGPUDiagnosticInfoUnsupported.h b/gnu/llvm/lib/Target/AMDGPU/AMDGPUDiagnosticInfoUnsupported.h deleted file mode 100644 index 0fd37e1ede6..00000000000 --- a/gnu/llvm/lib/Target/AMDGPU/AMDGPUDiagnosticInfoUnsupported.h +++ /dev/null @@ -1,48 +0,0 @@ -//===-- AMDGPUDiagnosticInfoUnsupported.h - Error reporting -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUDIAGNOSTICINFOUNSUPPORTED_H -#define LLVM_LIB_TARGET_AMDGPU_AMDGPUDIAGNOSTICINFOUNSUPPORTED_H - -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/DiagnosticPrinter.h" - -namespace llvm { - -/// Diagnostic information for unimplemented or unsupported feature reporting. -class DiagnosticInfoUnsupported : public DiagnosticInfo { -private: - const Twine &Description; - const Function &Fn; - - static int KindID; - - static int getKindID() { - if (KindID == 0) - KindID = llvm::getNextAvailablePluginDiagnosticKind(); - return KindID; - } - -public: - DiagnosticInfoUnsupported(const Function &Fn, const Twine &Desc, - DiagnosticSeverity Severity = DS_Error); - - const Function &getFunction() const { return Fn; } - const Twine &getDescription() const { return Description; } - - void print(DiagnosticPrinter &DP) const override; - - static bool classof(const DiagnosticInfo *DI) { - return DI->getKind() == getKindID(); - } -}; - -} - -#endif diff --git a/gnu/llvm/lib/Target/AMDGPU/AsmParser/Makefile b/gnu/llvm/lib/Target/AMDGPU/AsmParser/Makefile deleted file mode 100644 index 5ad21902803..00000000000 --- a/gnu/llvm/lib/Target/AMDGPU/AsmParser/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/AMDGPU/AsmParser/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMAMDGPUAsmParser - -# Hack: we need to include 'main' AMDGPU target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AMDGPU/InstPrinter/Makefile b/gnu/llvm/lib/Target/AMDGPU/InstPrinter/Makefile deleted file mode 100644 index 4e48ac7e28a..00000000000 --- a/gnu/llvm/lib/Target/AMDGPU/InstPrinter/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -#===- lib/Target/R600/AsmPrinter/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMAMDGPUAsmPrinter - -# Hack: we need to include 'main' x86 target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AMDGPU/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/AMDGPU/MCTargetDesc/Makefile deleted file mode 100644 index 5ad68662d98..00000000000 --- a/gnu/llvm/lib/Target/AMDGPU/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/AMDGPU/TargetDesc/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMAMDGPUDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AMDGPU/Makefile b/gnu/llvm/lib/Target/AMDGPU/Makefile deleted file mode 100644 index 219f34daa24..00000000000 --- a/gnu/llvm/lib/Target/AMDGPU/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -##===- lib/Target/R600/Makefile ---------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMAMDGPUCodeGen -TARGET = AMDGPU - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = AMDGPUGenRegisterInfo.inc AMDGPUGenInstrInfo.inc \ - AMDGPUGenDAGISel.inc AMDGPUGenSubtargetInfo.inc \ - AMDGPUGenMCCodeEmitter.inc AMDGPUGenCallingConv.inc \ - AMDGPUGenIntrinsics.inc AMDGPUGenDFAPacketizer.inc \ - AMDGPUGenAsmWriter.inc AMDGPUGenAsmMatcher.inc - -DIRS = AsmParser InstPrinter TargetInfo MCTargetDesc Utils - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AMDGPU/R600TextureIntrinsicsReplacer.cpp b/gnu/llvm/lib/Target/AMDGPU/R600TextureIntrinsicsReplacer.cpp deleted file mode 100644 index 2fc7b02f673..00000000000 --- a/gnu/llvm/lib/Target/AMDGPU/R600TextureIntrinsicsReplacer.cpp +++ /dev/null @@ -1,303 +0,0 @@ -//===-- R600TextureIntrinsicsReplacer.cpp ---------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This pass translates tgsi-like texture intrinsics into R600 texture -/// closer to hardware intrinsics. -//===----------------------------------------------------------------------===// - -#include "AMDGPU.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InstVisitor.h" - -using namespace llvm; - -namespace { -class R600TextureIntrinsicsReplacer : - public FunctionPass, public InstVisitor<R600TextureIntrinsicsReplacer> { - static char ID; - - Module *Mod; - Type *FloatType; - Type *Int32Type; - Type *V4f32Type; - Type *V4i32Type; - FunctionType *TexSign; - FunctionType *TexQSign; - - void getAdjustmentFromTextureTarget(unsigned TextureType, bool hasLOD, - unsigned SrcSelect[4], unsigned CT[4], - bool &useShadowVariant) { - enum TextureTypes { - TEXTURE_1D = 1, - TEXTURE_2D, - TEXTURE_3D, - TEXTURE_CUBE, - TEXTURE_RECT, - TEXTURE_SHADOW1D, - TEXTURE_SHADOW2D, - TEXTURE_SHADOWRECT, - TEXTURE_1D_ARRAY, - TEXTURE_2D_ARRAY, - TEXTURE_SHADOW1D_ARRAY, - TEXTURE_SHADOW2D_ARRAY, - TEXTURE_SHADOWCUBE, - TEXTURE_2D_MSAA, - TEXTURE_2D_ARRAY_MSAA, - TEXTURE_CUBE_ARRAY, - TEXTURE_SHADOWCUBE_ARRAY - }; - - switch (TextureType) { - case 0: - useShadowVariant = false; - return; - case TEXTURE_RECT: - case TEXTURE_1D: - case TEXTURE_2D: - case TEXTURE_3D: - case TEXTURE_CUBE: - case TEXTURE_1D_ARRAY: - case TEXTURE_2D_ARRAY: - case TEXTURE_CUBE_ARRAY: - case TEXTURE_2D_MSAA: - case TEXTURE_2D_ARRAY_MSAA: - useShadowVariant = false; - break; - case TEXTURE_SHADOW1D: - case TEXTURE_SHADOW2D: - case TEXTURE_SHADOWRECT: - case TEXTURE_SHADOW1D_ARRAY: - case TEXTURE_SHADOW2D_ARRAY: - case TEXTURE_SHADOWCUBE: - case TEXTURE_SHADOWCUBE_ARRAY: - useShadowVariant = true; - break; - default: - llvm_unreachable("Unknow Texture Type"); - } - - if (TextureType == TEXTURE_RECT || - TextureType == TEXTURE_SHADOWRECT) { - CT[0] = 0; - CT[1] = 0; - } - - if (TextureType == TEXTURE_CUBE_ARRAY || - TextureType == TEXTURE_SHADOWCUBE_ARRAY) - CT[2] = 0; - - if (TextureType == TEXTURE_1D_ARRAY || - TextureType == TEXTURE_SHADOW1D_ARRAY) { - if (hasLOD && useShadowVariant) { - CT[1] = 0; - } else { - CT[2] = 0; - SrcSelect[2] = 1; - } - } else if (TextureType == TEXTURE_2D_ARRAY || - TextureType == TEXTURE_SHADOW2D_ARRAY) { - CT[2] = 0; - } - - if ((TextureType == TEXTURE_SHADOW1D || - TextureType == TEXTURE_SHADOW2D || - TextureType == TEXTURE_SHADOWRECT || - TextureType == TEXTURE_SHADOW1D_ARRAY) && - !(hasLOD && useShadowVariant)) - SrcSelect[3] = 2; - } - - void ReplaceCallInst(CallInst &I, FunctionType *FT, const char *Name, - unsigned SrcSelect[4], Value *Offset[3], Value *Resource, - Value *Sampler, unsigned CT[4], Value *Coord) { - IRBuilder<> Builder(&I); - Constant *Mask[] = { - ConstantInt::get(Int32Type, SrcSelect[0]), - ConstantInt::get(Int32Type, SrcSelect[1]), - ConstantInt::get(Int32Type, SrcSelect[2]), - ConstantInt::get(Int32Type, SrcSelect[3]) - }; - Value *SwizzleMask = ConstantVector::get(Mask); - Value *SwizzledCoord = - Builder.CreateShuffleVector(Coord, Coord, SwizzleMask); - - Value *Args[] = { - SwizzledCoord, - Offset[0], - Offset[1], - Offset[2], - Resource, - Sampler, - ConstantInt::get(Int32Type, CT[0]), - ConstantInt::get(Int32Type, CT[1]), - ConstantInt::get(Int32Type, CT[2]), - ConstantInt::get(Int32Type, CT[3]) - }; - - Function *F = Mod->getFunction(Name); - if (!F) { - F = Function::Create(FT, GlobalValue::ExternalLinkage, Name, Mod); - F->addFnAttr(Attribute::ReadNone); - } - I.replaceAllUsesWith(Builder.CreateCall(F, Args)); - I.eraseFromParent(); - } - - void ReplaceTexIntrinsic(CallInst &I, bool hasLOD, FunctionType *FT, - const char *VanillaInt, - const char *ShadowInt) { - Value *Coord = I.getArgOperand(0); - Value *ResourceId = I.getArgOperand(1); - Value *SamplerId = I.getArgOperand(2); - - unsigned TextureType = - cast<ConstantInt>(I.getArgOperand(3))->getZExtValue(); - - unsigned SrcSelect[4] = { 0, 1, 2, 3 }; - unsigned CT[4] = {1, 1, 1, 1}; - Value *Offset[3] = { - ConstantInt::get(Int32Type, 0), - ConstantInt::get(Int32Type, 0), - ConstantInt::get(Int32Type, 0) - }; - bool useShadowVariant; - - getAdjustmentFromTextureTarget(TextureType, hasLOD, SrcSelect, CT, - useShadowVariant); - - ReplaceCallInst(I, FT, useShadowVariant?ShadowInt:VanillaInt, SrcSelect, - Offset, ResourceId, SamplerId, CT, Coord); - } - - void ReplaceTXF(CallInst &I) { - Value *Coord = I.getArgOperand(0); - Value *ResourceId = I.getArgOperand(4); - Value *SamplerId = I.getArgOperand(5); - - unsigned TextureType = - cast<ConstantInt>(I.getArgOperand(6))->getZExtValue(); - - unsigned SrcSelect[4] = { 0, 1, 2, 3 }; - unsigned CT[4] = {1, 1, 1, 1}; - Value *Offset[3] = { - I.getArgOperand(1), - I.getArgOperand(2), - I.getArgOperand(3), - }; - bool useShadowVariant; - - getAdjustmentFromTextureTarget(TextureType, false, SrcSelect, CT, - useShadowVariant); - - ReplaceCallInst(I, TexQSign, "llvm.R600.txf", SrcSelect, - Offset, ResourceId, SamplerId, CT, Coord); - } - -public: - R600TextureIntrinsicsReplacer(): - FunctionPass(ID) { - } - - bool doInitialization(Module &M) override { - LLVMContext &Ctx = M.getContext(); - Mod = &M; - FloatType = Type::getFloatTy(Ctx); - Int32Type = Type::getInt32Ty(Ctx); - V4f32Type = VectorType::get(FloatType, 4); - V4i32Type = VectorType::get(Int32Type, 4); - Type *ArgsType[] = { - V4f32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - }; - TexSign = FunctionType::get(V4f32Type, ArgsType, /*isVarArg=*/false); - Type *ArgsQType[] = { - V4i32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - Int32Type, - }; - TexQSign = FunctionType::get(V4f32Type, ArgsQType, /*isVarArg=*/false); - return false; - } - - bool runOnFunction(Function &F) override { - visit(F); - return false; - } - - const char *getPassName() const override { - return "R600 Texture Intrinsics Replacer"; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - } - - void visitCallInst(CallInst &I) { - if (!I.getCalledFunction()) - return; - - StringRef Name = I.getCalledFunction()->getName(); - if (Name == "llvm.AMDGPU.tex") { - ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.tex", "llvm.R600.texc"); - return; - } - if (Name == "llvm.AMDGPU.txl") { - ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txl", "llvm.R600.txlc"); - return; - } - if (Name == "llvm.AMDGPU.txb") { - ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txb", "llvm.R600.txbc"); - return; - } - if (Name == "llvm.AMDGPU.txf") { - ReplaceTXF(I); - return; - } - if (Name == "llvm.AMDGPU.txq") { - ReplaceTexIntrinsic(I, false, TexQSign, "llvm.R600.txq", "llvm.R600.txq"); - return; - } - if (Name == "llvm.AMDGPU.ddx") { - ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddx", "llvm.R600.ddx"); - return; - } - if (Name == "llvm.AMDGPU.ddy") { - ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddy", "llvm.R600.ddy"); - return; - } - } - -}; - -char R600TextureIntrinsicsReplacer::ID = 0; - -} - -FunctionPass *llvm::createR600TextureIntrinsicsReplacer() { - return new R600TextureIntrinsicsReplacer(); -} diff --git a/gnu/llvm/lib/Target/AMDGPU/SIFixSGPRLiveRanges.cpp b/gnu/llvm/lib/Target/AMDGPU/SIFixSGPRLiveRanges.cpp deleted file mode 100644 index 8bda283f0fc..00000000000 --- a/gnu/llvm/lib/Target/AMDGPU/SIFixSGPRLiveRanges.cpp +++ /dev/null @@ -1,219 +0,0 @@ -//===-- SIFixSGPRLiveRanges.cpp - Fix SGPR live ranges ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// \file SALU instructions ignore the execution mask, so we need to modify the -/// live ranges of the registers they define in some cases. -/// -/// The main case we need to handle is when a def is used in one side of a -/// branch and not another. For example: -/// -/// %def -/// IF -/// ... -/// ... -/// ELSE -/// %use -/// ... -/// ENDIF -/// -/// Here we need the register allocator to avoid assigning any of the defs -/// inside of the IF to the same register as %def. In traditional live -/// interval analysis %def is not live inside the IF branch, however, since -/// SALU instructions inside of IF will be executed even if the branch is not -/// taken, there is the chance that one of the instructions will overwrite the -/// value of %def, so the use in ELSE will see the wrong value. -/// -/// The strategy we use for solving this is to add an extra use after the ENDIF: -/// -/// %def -/// IF -/// ... -/// ... -/// ELSE -/// %use -/// ... -/// ENDIF -/// %use -/// -/// Adding this use will make the def live throughout the IF branch, which is -/// what we want. - -#include "AMDGPU.h" -#include "SIInstrInfo.h" -#include "SIRegisterInfo.h" -#include "llvm/ADT/DepthFirstIterator.h" -#include "llvm/CodeGen/LiveIntervalAnalysis.h" -#include "llvm/CodeGen/LiveVariables.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachinePostDominators.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" - -using namespace llvm; - -#define DEBUG_TYPE "si-fix-sgpr-live-ranges" - -namespace { - -class SIFixSGPRLiveRanges : public MachineFunctionPass { -public: - static char ID; - -public: - SIFixSGPRLiveRanges() : MachineFunctionPass(ID) { - initializeSIFixSGPRLiveRangesPass(*PassRegistry::getPassRegistry()); - } - - bool runOnMachineFunction(MachineFunction &MF) override; - - const char *getPassName() const override { - return "SI Fix SGPR live ranges"; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<LiveVariables>(); - AU.addPreserved<LiveVariables>(); - - AU.addRequired<MachinePostDominatorTree>(); - AU.addPreserved<MachinePostDominatorTree>(); - AU.setPreservesCFG(); - - MachineFunctionPass::getAnalysisUsage(AU); - } -}; - -} // End anonymous namespace. - -INITIALIZE_PASS_BEGIN(SIFixSGPRLiveRanges, DEBUG_TYPE, - "SI Fix SGPR Live Ranges", false, false) -INITIALIZE_PASS_DEPENDENCY(LiveVariables) -INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree) -INITIALIZE_PASS_END(SIFixSGPRLiveRanges, DEBUG_TYPE, - "SI Fix SGPR Live Ranges", false, false) - -char SIFixSGPRLiveRanges::ID = 0; - -char &llvm::SIFixSGPRLiveRangesID = SIFixSGPRLiveRanges::ID; - -FunctionPass *llvm::createSIFixSGPRLiveRangesPass() { - return new SIFixSGPRLiveRanges(); -} - -bool SIFixSGPRLiveRanges::runOnMachineFunction(MachineFunction &MF) { - MachineRegisterInfo &MRI = MF.getRegInfo(); - const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); - const SIRegisterInfo *TRI = static_cast<const SIRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - bool MadeChange = false; - - MachinePostDominatorTree *PDT = &getAnalysis<MachinePostDominatorTree>(); - SmallVector<unsigned, 16> SGPRLiveRanges; - - LiveVariables *LV = &getAnalysis<LiveVariables>(); - MachineBasicBlock *Entry = &MF.front(); - - // Use a depth first order so that in SSA, we encounter all defs before - // uses. Once the defs of the block have been found, attempt to insert - // SGPR_USE instructions in successor blocks if required. - for (MachineBasicBlock *MBB : depth_first(Entry)) { - for (const MachineInstr &MI : *MBB) { - for (const MachineOperand &MO : MI.defs()) { - // We should never see a live out def of a physical register, so we also - // do not need to worry about implicit_defs(). - unsigned Def = MO.getReg(); - if (TargetRegisterInfo::isVirtualRegister(Def)) { - if (TRI->isSGPRClass(MRI.getRegClass(Def))) { - // Only consider defs that are live outs. We don't care about def / - // use within the same block. - - // LiveVariables does not consider registers that are only used in a - // phi in a sucessor block as live out, unlike LiveIntervals. - // - // This is OK because SIFixSGPRCopies replaced any SGPR phis with - // VGPRs. - if (LV->isLiveOut(Def, *MBB)) - SGPRLiveRanges.push_back(Def); - } - } - } - } - - if (MBB->succ_size() < 2) - continue; - - // We have structured control flow, so the number of successors should be - // two. - assert(MBB->succ_size() == 2); - MachineBasicBlock *SuccA = *MBB->succ_begin(); - MachineBasicBlock *SuccB = *(++MBB->succ_begin()); - MachineBasicBlock *NCD = PDT->findNearestCommonDominator(SuccA, SuccB); - - if (!NCD) - continue; - - MachineBasicBlock::iterator NCDTerm = NCD->getFirstTerminator(); - - if (NCDTerm != NCD->end() && NCDTerm->getOpcode() == AMDGPU::SI_ELSE) { - assert(NCD->succ_size() == 2); - // We want to make sure we insert the Use after the ENDIF, not after - // the ELSE. - NCD = PDT->findNearestCommonDominator(*NCD->succ_begin(), - *(++NCD->succ_begin())); - } - - for (unsigned Reg : SGPRLiveRanges) { - // FIXME: We could be smarter here. If the register is Live-In to one - // block, but the other doesn't have any SGPR defs, then there won't be a - // conflict. Also, if the branch condition is uniform then there will be - // no conflict. - bool LiveInToA = LV->isLiveIn(Reg, *SuccA); - bool LiveInToB = LV->isLiveIn(Reg, *SuccB); - - if (!LiveInToA && !LiveInToB) { - DEBUG(dbgs() << PrintReg(Reg, TRI, 0) - << " is live into neither successor\n"); - continue; - } - - if (LiveInToA && LiveInToB) { - DEBUG(dbgs() << PrintReg(Reg, TRI, 0) - << " is live into both successors\n"); - continue; - } - - // This interval is live in to one successor, but not the other, so - // we need to update its range so it is live in to both. - DEBUG(dbgs() << "Possible SGPR conflict detected for " - << PrintReg(Reg, TRI, 0) - << " BB#" << SuccA->getNumber() - << ", BB#" << SuccB->getNumber() - << " with NCD = BB#" << NCD->getNumber() << '\n'); - - assert(TargetRegisterInfo::isVirtualRegister(Reg) && - "Not expecting to extend live range of physreg"); - - // FIXME: Need to figure out how to update LiveRange here so this pass - // will be able to preserve LiveInterval analysis. - MachineInstr *NCDSGPRUse = - BuildMI(*NCD, NCD->getFirstNonPHI(), DebugLoc(), - TII->get(AMDGPU::SGPR_USE)) - .addReg(Reg, RegState::Implicit); - - MadeChange = true; - LV->HandleVirtRegUse(Reg, NCD, NCDSGPRUse); - - DEBUG(NCDSGPRUse->dump()); - } - } - - return MadeChange; -} diff --git a/gnu/llvm/lib/Target/AMDGPU/TargetInfo/Makefile b/gnu/llvm/lib/Target/AMDGPU/TargetInfo/Makefile deleted file mode 100644 index 1b232871bd6..00000000000 --- a/gnu/llvm/lib/Target/AMDGPU/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/AMDGPU/TargetInfo/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMAMDGPUInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AMDGPU/Utils/Makefile b/gnu/llvm/lib/Target/AMDGPU/Utils/Makefile deleted file mode 100644 index 1019e726d50..00000000000 --- a/gnu/llvm/lib/Target/AMDGPU/Utils/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/AMDGPU/Utils/Makefile --------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMAMDGPUUtils - -# Hack: we need to include 'main' AMDGPU target directory to grab private -# headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/ARM/AsmParser/Makefile b/gnu/llvm/lib/Target/ARM/AsmParser/Makefile deleted file mode 100644 index 841516fffbd..00000000000 --- a/gnu/llvm/lib/Target/ARM/AsmParser/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/ARM/AsmParser/Makefile -------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMARMAsmParser - -# Hack: we need to include 'main' ARM target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/ARM/Disassembler/Makefile b/gnu/llvm/lib/Target/ARM/Disassembler/Makefile deleted file mode 100644 index 031b6aca5a4..00000000000 --- a/gnu/llvm/lib/Target/ARM/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/ARM/Disassembler/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMARMDisassembler - -# Hack: we need to include 'main' arm target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/ARM/InstPrinter/Makefile b/gnu/llvm/lib/Target/ARM/InstPrinter/Makefile deleted file mode 100644 index 65d372e44b8..00000000000 --- a/gnu/llvm/lib/Target/ARM/InstPrinter/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/ARM/AsmPrinter/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMARMAsmPrinter - -# Hack: we need to include 'main' arm target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/ARM/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/ARM/MCTargetDesc/Makefile deleted file mode 100644 index 448ed9df2bf..00000000000 --- a/gnu/llvm/lib/Target/ARM/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/ARM/TargetDesc/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMARMDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/ARM/Makefile b/gnu/llvm/lib/Target/ARM/Makefile deleted file mode 100644 index c1601a3f29d..00000000000 --- a/gnu/llvm/lib/Target/ARM/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -##===- lib/Target/ARM/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMARMCodeGen -TARGET = ARM - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = ARMGenRegisterInfo.inc ARMGenInstrInfo.inc \ - ARMGenAsmWriter.inc ARMGenAsmMatcher.inc \ - ARMGenDAGISel.inc ARMGenSubtargetInfo.inc \ - ARMGenCallingConv.inc \ - ARMGenFastISel.inc ARMGenMCCodeEmitter.inc \ - ARMGenMCPseudoLowering.inc ARMGenDisassemblerTables.inc - -DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/ARM/TargetInfo/Makefile b/gnu/llvm/lib/Target/ARM/TargetInfo/Makefile deleted file mode 100644 index 6292ab14b34..00000000000 --- a/gnu/llvm/lib/Target/ARM/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/ARM/TargetInfo/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMARMInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AVR/AVRConfig.h b/gnu/llvm/lib/Target/AVR/AVRConfig.h deleted file mode 100644 index 65588bc5084..00000000000 --- a/gnu/llvm/lib/Target/AVR/AVRConfig.h +++ /dev/null @@ -1,15 +0,0 @@ -//===-- AVRConfig.h - AVR Backend Configuration Header ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_AVR_CONFIG_H -#define LLVM_AVR_CONFIG_H - -#define LLVM_AVR_GCC_COMPAT - -#endif // LLVM_AVR_CONFIG_H diff --git a/gnu/llvm/lib/Target/AVR/Makefile b/gnu/llvm/lib/Target/AVR/Makefile deleted file mode 100644 index c91b6f5c0ae..00000000000 --- a/gnu/llvm/lib/Target/AVR/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -##===- lib/Target/AVR/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMAVRCodeGen -TARGET = AVR - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = AVRGenRegisterInfo.inc - -DIRS = TargetInfo - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/AVR/TargetInfo/Makefile b/gnu/llvm/lib/Target/AVR/TargetInfo/Makefile deleted file mode 100644 index 92b483dd028..00000000000 --- a/gnu/llvm/lib/Target/AVR/TargetInfo/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/AVR/TargetInfo/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMAVRInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/BPF/InstPrinter/Makefile b/gnu/llvm/lib/Target/BPF/InstPrinter/Makefile deleted file mode 100644 index f46af83346d..00000000000 --- a/gnu/llvm/lib/Target/BPF/InstPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/BPF/InstPrinter/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMBPFAsmPrinter - -# Hack: we need to include 'main' BPF target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/BPF/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/BPF/MCTargetDesc/Makefile deleted file mode 100644 index af70cd059e5..00000000000 --- a/gnu/llvm/lib/Target/BPF/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/BPF/MCTargetDesc/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMBPFDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/BPF/Makefile b/gnu/llvm/lib/Target/BPF/Makefile deleted file mode 100644 index 7492f5edd51..00000000000 --- a/gnu/llvm/lib/Target/BPF/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -##===- lib/Target/BPF/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMBPFCodeGen -TARGET = BPF - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = BPFGenRegisterInfo.inc BPFGenInstrInfo.inc \ - BPFGenAsmWriter.inc BPFGenAsmMatcher.inc BPFGenDAGISel.inc \ - BPFGenMCCodeEmitter.inc BPFGenSubtargetInfo.inc BPFGenCallingConv.inc - -DIRS = InstPrinter TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/BPF/TargetInfo/Makefile b/gnu/llvm/lib/Target/BPF/TargetInfo/Makefile deleted file mode 100644 index 02af58ea187..00000000000 --- a/gnu/llvm/lib/Target/BPF/TargetInfo/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/BPF/TargetInfo/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMBPFInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/CppBackend/CMakeLists.txt b/gnu/llvm/lib/Target/CppBackend/CMakeLists.txt deleted file mode 100644 index 515e1dd7e39..00000000000 --- a/gnu/llvm/lib/Target/CppBackend/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_llvm_target(CppBackendCodeGen - CPPBackend.cpp - ) - -add_subdirectory(TargetInfo) diff --git a/gnu/llvm/lib/Target/CppBackend/CPPBackend.cpp b/gnu/llvm/lib/Target/CppBackend/CPPBackend.cpp deleted file mode 100644 index 5ea6551ebc9..00000000000 --- a/gnu/llvm/lib/Target/CppBackend/CPPBackend.cpp +++ /dev/null @@ -1,2143 +0,0 @@ -//===-- CPPBackend.cpp - Library for converting LLVM code to C++ code -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the writing of the LLVM IR as a set of C++ calls to the -// LLVM IR interface. The input module is assumed to be verified. -// -//===----------------------------------------------------------------------===// - -#include "CPPTargetMachine.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Config/config.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Module.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Pass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/TargetRegistry.h" -#include <algorithm> -#include <cctype> -#include <cstdio> -#include <map> -#include <set> -using namespace llvm; - -static cl::opt<std::string> -FuncName("cppfname", cl::desc("Specify the name of the generated function"), - cl::value_desc("function name")); - -enum WhatToGenerate { - GenProgram, - GenModule, - GenContents, - GenFunction, - GenFunctions, - GenInline, - GenVariable, - GenType -}; - -static cl::opt<WhatToGenerate> GenerationType("cppgen", cl::Optional, - cl::desc("Choose what kind of output to generate"), - cl::init(GenProgram), - cl::values( - clEnumValN(GenProgram, "program", "Generate a complete program"), - clEnumValN(GenModule, "module", "Generate a module definition"), - clEnumValN(GenContents, "contents", "Generate contents of a module"), - clEnumValN(GenFunction, "function", "Generate a function definition"), - clEnumValN(GenFunctions,"functions", "Generate all function definitions"), - clEnumValN(GenInline, "inline", "Generate an inline function"), - clEnumValN(GenVariable, "variable", "Generate a variable definition"), - clEnumValN(GenType, "type", "Generate a type definition"), - clEnumValEnd - ) -); - -static cl::opt<std::string> NameToGenerate("cppfor", cl::Optional, - cl::desc("Specify the name of the thing to generate"), - cl::init("!bad!")); - -extern "C" void LLVMInitializeCppBackendTarget() { - // Register the target. - RegisterTargetMachine<CPPTargetMachine> X(TheCppBackendTarget); -} - -namespace { - typedef std::vector<Type*> TypeList; - typedef std::map<Type*,std::string> TypeMap; - typedef std::map<const Value*,std::string> ValueMap; - typedef std::set<std::string> NameSet; - typedef std::set<Type*> TypeSet; - typedef std::set<const Value*> ValueSet; - typedef std::map<const Value*,std::string> ForwardRefMap; - - /// CppWriter - This class is the main chunk of code that converts an LLVM - /// module to a C++ translation unit. - class CppWriter : public ModulePass { - std::unique_ptr<formatted_raw_ostream> OutOwner; - formatted_raw_ostream &Out; - const Module *TheModule; - uint64_t uniqueNum; - TypeMap TypeNames; - ValueMap ValueNames; - NameSet UsedNames; - TypeSet DefinedTypes; - ValueSet DefinedValues; - ForwardRefMap ForwardRefs; - bool is_inline; - unsigned indent_level; - - public: - static char ID; - explicit CppWriter(std::unique_ptr<formatted_raw_ostream> o) - : ModulePass(ID), OutOwner(std::move(o)), Out(*OutOwner), uniqueNum(0), - is_inline(false), indent_level(0) {} - - const char *getPassName() const override { return "C++ backend"; } - - bool runOnModule(Module &M) override; - - void printProgram(const std::string& fname, const std::string& modName ); - void printModule(const std::string& fname, const std::string& modName ); - void printContents(const std::string& fname, const std::string& modName ); - void printFunction(const std::string& fname, const std::string& funcName ); - void printFunctions(); - void printInline(const std::string& fname, const std::string& funcName ); - void printVariable(const std::string& fname, const std::string& varName ); - void printType(const std::string& fname, const std::string& typeName ); - - void error(const std::string& msg); - - - formatted_raw_ostream& nl(formatted_raw_ostream &Out, int delta = 0); - inline void in() { indent_level++; } - inline void out() { if (indent_level >0) indent_level--; } - - private: - void printLinkageType(GlobalValue::LinkageTypes LT); - void printVisibilityType(GlobalValue::VisibilityTypes VisTypes); - void printDLLStorageClassType(GlobalValue::DLLStorageClassTypes DSCType); - void printThreadLocalMode(GlobalVariable::ThreadLocalMode TLM); - void printCallingConv(CallingConv::ID cc); - void printEscapedString(const std::string& str); - void printCFP(const ConstantFP* CFP); - - std::string getCppName(Type* val); - inline void printCppName(Type* val); - - std::string getCppName(const Value* val); - inline void printCppName(const Value* val); - - void printAttributes(const AttributeSet &PAL, const std::string &name); - void printType(Type* Ty); - void printTypes(const Module* M); - - void printConstant(const Constant *CPV); - void printConstants(const Module* M); - - void printVariableUses(const GlobalVariable *GV); - void printVariableHead(const GlobalVariable *GV); - void printVariableBody(const GlobalVariable *GV); - - void printFunctionUses(const Function *F); - void printFunctionHead(const Function *F); - void printFunctionBody(const Function *F); - void printInstruction(const Instruction *I, const std::string& bbname); - std::string getOpName(const Value*); - - void printModuleBody(); - }; -} // end anonymous namespace. - -formatted_raw_ostream &CppWriter::nl(formatted_raw_ostream &Out, int delta) { - Out << '\n'; - if (delta >= 0 || indent_level >= unsigned(-delta)) - indent_level += delta; - Out.indent(indent_level); - return Out; -} - -static inline void sanitize(std::string &str) { - for (size_t i = 0; i < str.length(); ++i) - if (!isalnum(str[i]) && str[i] != '_') - str[i] = '_'; -} - -static std::string getTypePrefix(Type *Ty) { - switch (Ty->getTypeID()) { - case Type::VoidTyID: return "void_"; - case Type::IntegerTyID: - return "int" + utostr(cast<IntegerType>(Ty)->getBitWidth()) + "_"; - case Type::FloatTyID: return "float_"; - case Type::DoubleTyID: return "double_"; - case Type::LabelTyID: return "label_"; - case Type::FunctionTyID: return "func_"; - case Type::StructTyID: return "struct_"; - case Type::ArrayTyID: return "array_"; - case Type::PointerTyID: return "ptr_"; - case Type::VectorTyID: return "packed_"; - default: return "other_"; - } -} - -void CppWriter::error(const std::string& msg) { - report_fatal_error(msg); -} - -static inline std::string ftostr(const APFloat& V) { - std::string Buf; - if (&V.getSemantics() == &APFloat::IEEEdouble) { - raw_string_ostream(Buf) << V.convertToDouble(); - return Buf; - } else if (&V.getSemantics() == &APFloat::IEEEsingle) { - raw_string_ostream(Buf) << (double)V.convertToFloat(); - return Buf; - } - return "<unknown format in ftostr>"; // error -} - -// printCFP - Print a floating point constant .. very carefully :) -// This makes sure that conversion to/from floating yields the same binary -// result so that we don't lose precision. -void CppWriter::printCFP(const ConstantFP *CFP) { - bool ignored; - APFloat APF = APFloat(CFP->getValueAPF()); // copy - if (CFP->getType() == Type::getFloatTy(CFP->getContext())) - APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored); - Out << "ConstantFP::get(mod->getContext(), "; - Out << "APFloat("; -#if HAVE_PRINTF_A - char Buffer[100]; - sprintf(Buffer, "%A", APF.convertToDouble()); - if ((!strncmp(Buffer, "0x", 2) || - !strncmp(Buffer, "-0x", 3) || - !strncmp(Buffer, "+0x", 3)) && - APF.bitwiseIsEqual(APFloat(atof(Buffer)))) { - if (CFP->getType() == Type::getDoubleTy(CFP->getContext())) - Out << "BitsToDouble(" << Buffer << ")"; - else - Out << "BitsToFloat((float)" << Buffer << ")"; - Out << ")"; - } else { -#endif - std::string StrVal = ftostr(CFP->getValueAPF()); - - while (StrVal[0] == ' ') - StrVal.erase(StrVal.begin()); - - // Check to make sure that the stringized number is not some string like - // "Inf" or NaN. Check that the string matches the "[-+]?[0-9]" regex. - if (((StrVal[0] >= '0' && StrVal[0] <= '9') || - ((StrVal[0] == '-' || StrVal[0] == '+') && - (StrVal[1] >= '0' && StrVal[1] <= '9'))) && - (CFP->isExactlyValue(atof(StrVal.c_str())))) { - if (CFP->getType() == Type::getDoubleTy(CFP->getContext())) - Out << StrVal; - else - Out << StrVal << "f"; - } else if (CFP->getType() == Type::getDoubleTy(CFP->getContext())) - Out << "BitsToDouble(0x" - << utohexstr(CFP->getValueAPF().bitcastToAPInt().getZExtValue()) - << "ULL) /* " << StrVal << " */"; - else - Out << "BitsToFloat(0x" - << utohexstr((uint32_t)CFP->getValueAPF(). - bitcastToAPInt().getZExtValue()) - << "U) /* " << StrVal << " */"; - Out << ")"; -#if HAVE_PRINTF_A - } -#endif - Out << ")"; -} - -void CppWriter::printCallingConv(CallingConv::ID cc){ - // Print the calling convention. - switch (cc) { - case CallingConv::C: Out << "CallingConv::C"; break; - case CallingConv::Fast: Out << "CallingConv::Fast"; break; - case CallingConv::Cold: Out << "CallingConv::Cold"; break; - case CallingConv::FirstTargetCC: Out << "CallingConv::FirstTargetCC"; break; - default: Out << cc; break; - } -} - -void CppWriter::printLinkageType(GlobalValue::LinkageTypes LT) { - switch (LT) { - case GlobalValue::InternalLinkage: - Out << "GlobalValue::InternalLinkage"; break; - case GlobalValue::PrivateLinkage: - Out << "GlobalValue::PrivateLinkage"; break; - case GlobalValue::AvailableExternallyLinkage: - Out << "GlobalValue::AvailableExternallyLinkage "; break; - case GlobalValue::LinkOnceAnyLinkage: - Out << "GlobalValue::LinkOnceAnyLinkage "; break; - case GlobalValue::LinkOnceODRLinkage: - Out << "GlobalValue::LinkOnceODRLinkage "; break; - case GlobalValue::WeakAnyLinkage: - Out << "GlobalValue::WeakAnyLinkage"; break; - case GlobalValue::WeakODRLinkage: - Out << "GlobalValue::WeakODRLinkage"; break; - case GlobalValue::AppendingLinkage: - Out << "GlobalValue::AppendingLinkage"; break; - case GlobalValue::ExternalLinkage: - Out << "GlobalValue::ExternalLinkage"; break; - case GlobalValue::ExternalWeakLinkage: - Out << "GlobalValue::ExternalWeakLinkage"; break; - case GlobalValue::CommonLinkage: - Out << "GlobalValue::CommonLinkage"; break; - } -} - -void CppWriter::printVisibilityType(GlobalValue::VisibilityTypes VisType) { - switch (VisType) { - case GlobalValue::DefaultVisibility: - Out << "GlobalValue::DefaultVisibility"; - break; - case GlobalValue::HiddenVisibility: - Out << "GlobalValue::HiddenVisibility"; - break; - case GlobalValue::ProtectedVisibility: - Out << "GlobalValue::ProtectedVisibility"; - break; - } -} - -void CppWriter::printDLLStorageClassType( - GlobalValue::DLLStorageClassTypes DSCType) { - switch (DSCType) { - case GlobalValue::DefaultStorageClass: - Out << "GlobalValue::DefaultStorageClass"; - break; - case GlobalValue::DLLImportStorageClass: - Out << "GlobalValue::DLLImportStorageClass"; - break; - case GlobalValue::DLLExportStorageClass: - Out << "GlobalValue::DLLExportStorageClass"; - break; - } -} - -void CppWriter::printThreadLocalMode(GlobalVariable::ThreadLocalMode TLM) { - switch (TLM) { - case GlobalVariable::NotThreadLocal: - Out << "GlobalVariable::NotThreadLocal"; - break; - case GlobalVariable::GeneralDynamicTLSModel: - Out << "GlobalVariable::GeneralDynamicTLSModel"; - break; - case GlobalVariable::LocalDynamicTLSModel: - Out << "GlobalVariable::LocalDynamicTLSModel"; - break; - case GlobalVariable::InitialExecTLSModel: - Out << "GlobalVariable::InitialExecTLSModel"; - break; - case GlobalVariable::LocalExecTLSModel: - Out << "GlobalVariable::LocalExecTLSModel"; - break; - } -} - -// printEscapedString - Print each character of the specified string, escaping -// it if it is not printable or if it is an escape char. -void CppWriter::printEscapedString(const std::string &Str) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) { - unsigned char C = Str[i]; - if (isprint(C) && C != '"' && C != '\\') { - Out << C; - } else { - Out << "\\x" - << (char) ((C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A')) - << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A')); - } - } -} - -std::string CppWriter::getCppName(Type* Ty) { - switch (Ty->getTypeID()) { - default: - break; - case Type::VoidTyID: - return "Type::getVoidTy(mod->getContext())"; - case Type::IntegerTyID: { - unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth(); - return "IntegerType::get(mod->getContext(), " + utostr(BitWidth) + ")"; - } - case Type::X86_FP80TyID: - return "Type::getX86_FP80Ty(mod->getContext())"; - case Type::FloatTyID: - return "Type::getFloatTy(mod->getContext())"; - case Type::DoubleTyID: - return "Type::getDoubleTy(mod->getContext())"; - case Type::LabelTyID: - return "Type::getLabelTy(mod->getContext())"; - case Type::X86_MMXTyID: - return "Type::getX86_MMXTy(mod->getContext())"; - } - - // Now, see if we've seen the type before and return that - TypeMap::iterator I = TypeNames.find(Ty); - if (I != TypeNames.end()) - return I->second; - - // Okay, let's build a new name for this type. Start with a prefix - const char* prefix = nullptr; - switch (Ty->getTypeID()) { - case Type::FunctionTyID: prefix = "FuncTy_"; break; - case Type::StructTyID: prefix = "StructTy_"; break; - case Type::ArrayTyID: prefix = "ArrayTy_"; break; - case Type::PointerTyID: prefix = "PointerTy_"; break; - case Type::VectorTyID: prefix = "VectorTy_"; break; - default: prefix = "OtherTy_"; break; // prevent breakage - } - - // See if the type has a name in the symboltable and build accordingly - std::string name; - if (StructType *STy = dyn_cast<StructType>(Ty)) - if (STy->hasName()) - name = STy->getName(); - - if (name.empty()) - name = utostr(uniqueNum++); - - name = std::string(prefix) + name; - sanitize(name); - - // Save the name - return TypeNames[Ty] = name; -} - -void CppWriter::printCppName(Type* Ty) { - printEscapedString(getCppName(Ty)); -} - -std::string CppWriter::getCppName(const Value* val) { - std::string name; - ValueMap::iterator I = ValueNames.find(val); - if (I != ValueNames.end() && I->first == val) - return I->second; - - if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(val)) { - name = std::string("gvar_") + - getTypePrefix(GV->getType()->getElementType()); - } else if (isa<Function>(val)) { - name = std::string("func_"); - } else if (const Constant* C = dyn_cast<Constant>(val)) { - name = std::string("const_") + getTypePrefix(C->getType()); - } else if (const Argument* Arg = dyn_cast<Argument>(val)) { - if (is_inline) { - unsigned argNum = std::distance(Arg->getParent()->arg_begin(), - Function::const_arg_iterator(Arg)) + 1; - name = std::string("arg_") + utostr(argNum); - NameSet::iterator NI = UsedNames.find(name); - if (NI != UsedNames.end()) - name += std::string("_") + utostr(uniqueNum++); - UsedNames.insert(name); - return ValueNames[val] = name; - } else { - name = getTypePrefix(val->getType()); - } - } else { - name = getTypePrefix(val->getType()); - } - if (val->hasName()) - name += val->getName(); - else - name += utostr(uniqueNum++); - sanitize(name); - NameSet::iterator NI = UsedNames.find(name); - if (NI != UsedNames.end()) - name += std::string("_") + utostr(uniqueNum++); - UsedNames.insert(name); - return ValueNames[val] = name; -} - -void CppWriter::printCppName(const Value* val) { - printEscapedString(getCppName(val)); -} - -void CppWriter::printAttributes(const AttributeSet &PAL, - const std::string &name) { - Out << "AttributeSet " << name << "_PAL;"; - nl(Out); - if (!PAL.isEmpty()) { - Out << '{'; in(); nl(Out); - Out << "SmallVector<AttributeSet, 4> Attrs;"; nl(Out); - Out << "AttributeSet PAS;"; in(); nl(Out); - for (unsigned i = 0; i < PAL.getNumSlots(); ++i) { - unsigned index = PAL.getSlotIndex(i); - AttrBuilder attrs(PAL.getSlotAttributes(i), index); - Out << "{"; in(); nl(Out); - Out << "AttrBuilder B;"; nl(Out); - -#define HANDLE_ATTR(X) \ - if (attrs.contains(Attribute::X)) { \ - Out << "B.addAttribute(Attribute::" #X ");"; nl(Out); \ - attrs.removeAttribute(Attribute::X); \ - } - - HANDLE_ATTR(SExt); - HANDLE_ATTR(ZExt); - HANDLE_ATTR(NoReturn); - HANDLE_ATTR(InReg); - HANDLE_ATTR(StructRet); - HANDLE_ATTR(NoUnwind); - HANDLE_ATTR(NoAlias); - HANDLE_ATTR(ByVal); - HANDLE_ATTR(InAlloca); - HANDLE_ATTR(Nest); - HANDLE_ATTR(ReadNone); - HANDLE_ATTR(ReadOnly); - HANDLE_ATTR(NoInline); - HANDLE_ATTR(AlwaysInline); - HANDLE_ATTR(OptimizeNone); - HANDLE_ATTR(OptimizeForSize); - HANDLE_ATTR(StackProtect); - HANDLE_ATTR(StackProtectReq); - HANDLE_ATTR(StackProtectStrong); - HANDLE_ATTR(SafeStack); - HANDLE_ATTR(NoCapture); - HANDLE_ATTR(NoRedZone); - HANDLE_ATTR(NoImplicitFloat); - HANDLE_ATTR(Naked); - HANDLE_ATTR(InlineHint); - HANDLE_ATTR(ReturnsTwice); - HANDLE_ATTR(UWTable); - HANDLE_ATTR(NonLazyBind); - HANDLE_ATTR(MinSize); -#undef HANDLE_ATTR - - if (attrs.contains(Attribute::StackAlignment)) { - Out << "B.addStackAlignmentAttr(" << attrs.getStackAlignment()<<')'; - nl(Out); - attrs.removeAttribute(Attribute::StackAlignment); - } - - Out << "PAS = AttributeSet::get(mod->getContext(), "; - if (index == ~0U) - Out << "~0U,"; - else - Out << index << "U,"; - Out << " B);"; out(); nl(Out); - Out << "}"; out(); nl(Out); - nl(Out); - Out << "Attrs.push_back(PAS);"; nl(Out); - } - Out << name << "_PAL = AttributeSet::get(mod->getContext(), Attrs);"; - nl(Out); - out(); nl(Out); - Out << '}'; nl(Out); - } -} - -void CppWriter::printType(Type* Ty) { - // We don't print definitions for primitive types - if (Ty->isFloatingPointTy() || Ty->isX86_MMXTy() || Ty->isIntegerTy() || - Ty->isLabelTy() || Ty->isMetadataTy() || Ty->isVoidTy() || - Ty->isTokenTy()) - return; - - // If we already defined this type, we don't need to define it again. - if (DefinedTypes.find(Ty) != DefinedTypes.end()) - return; - - // Everything below needs the name for the type so get it now. - std::string typeName(getCppName(Ty)); - - // Print the type definition - switch (Ty->getTypeID()) { - case Type::FunctionTyID: { - FunctionType* FT = cast<FunctionType>(Ty); - Out << "std::vector<Type*>" << typeName << "_args;"; - nl(Out); - FunctionType::param_iterator PI = FT->param_begin(); - FunctionType::param_iterator PE = FT->param_end(); - for (; PI != PE; ++PI) { - Type* argTy = static_cast<Type*>(*PI); - printType(argTy); - std::string argName(getCppName(argTy)); - Out << typeName << "_args.push_back(" << argName; - Out << ");"; - nl(Out); - } - printType(FT->getReturnType()); - std::string retTypeName(getCppName(FT->getReturnType())); - Out << "FunctionType* " << typeName << " = FunctionType::get("; - in(); nl(Out) << "/*Result=*/" << retTypeName; - Out << ","; - nl(Out) << "/*Params=*/" << typeName << "_args,"; - nl(Out) << "/*isVarArg=*/" << (FT->isVarArg() ? "true" : "false") << ");"; - out(); - nl(Out); - break; - } - case Type::StructTyID: { - StructType* ST = cast<StructType>(Ty); - if (!ST->isLiteral()) { - Out << "StructType *" << typeName << " = mod->getTypeByName(\""; - printEscapedString(ST->getName()); - Out << "\");"; - nl(Out); - Out << "if (!" << typeName << ") {"; - nl(Out); - Out << typeName << " = "; - Out << "StructType::create(mod->getContext(), \""; - printEscapedString(ST->getName()); - Out << "\");"; - nl(Out); - Out << "}"; - nl(Out); - // Indicate that this type is now defined. - DefinedTypes.insert(Ty); - } - - Out << "std::vector<Type*>" << typeName << "_fields;"; - nl(Out); - StructType::element_iterator EI = ST->element_begin(); - StructType::element_iterator EE = ST->element_end(); - for (; EI != EE; ++EI) { - Type* fieldTy = static_cast<Type*>(*EI); - printType(fieldTy); - std::string fieldName(getCppName(fieldTy)); - Out << typeName << "_fields.push_back(" << fieldName; - Out << ");"; - nl(Out); - } - - if (ST->isLiteral()) { - Out << "StructType *" << typeName << " = "; - Out << "StructType::get(" << "mod->getContext(), "; - } else { - Out << "if (" << typeName << "->isOpaque()) {"; - nl(Out); - Out << typeName << "->setBody("; - } - - Out << typeName << "_fields, /*isPacked=*/" - << (ST->isPacked() ? "true" : "false") << ");"; - nl(Out); - if (!ST->isLiteral()) { - Out << "}"; - nl(Out); - } - break; - } - case Type::ArrayTyID: { - ArrayType* AT = cast<ArrayType>(Ty); - Type* ET = AT->getElementType(); - printType(ET); - if (DefinedTypes.find(Ty) == DefinedTypes.end()) { - std::string elemName(getCppName(ET)); - Out << "ArrayType* " << typeName << " = ArrayType::get(" - << elemName << ", " << AT->getNumElements() << ");"; - nl(Out); - } - break; - } - case Type::PointerTyID: { - PointerType* PT = cast<PointerType>(Ty); - Type* ET = PT->getElementType(); - printType(ET); - if (DefinedTypes.find(Ty) == DefinedTypes.end()) { - std::string elemName(getCppName(ET)); - Out << "PointerType* " << typeName << " = PointerType::get(" - << elemName << ", " << PT->getAddressSpace() << ");"; - nl(Out); - } - break; - } - case Type::VectorTyID: { - VectorType* PT = cast<VectorType>(Ty); - Type* ET = PT->getElementType(); - printType(ET); - if (DefinedTypes.find(Ty) == DefinedTypes.end()) { - std::string elemName(getCppName(ET)); - Out << "VectorType* " << typeName << " = VectorType::get(" - << elemName << ", " << PT->getNumElements() << ");"; - nl(Out); - } - break; - } - default: - error("Invalid TypeID"); - } - - // Indicate that this type is now defined. - DefinedTypes.insert(Ty); - - // Finally, separate the type definition from other with a newline. - nl(Out); -} - -void CppWriter::printTypes(const Module* M) { - // Add all of the global variables to the value table. - for (Module::const_global_iterator I = TheModule->global_begin(), - E = TheModule->global_end(); I != E; ++I) { - if (I->hasInitializer()) - printType(I->getInitializer()->getType()); - printType(I->getType()); - } - - // Add all the functions to the table - for (Module::const_iterator FI = TheModule->begin(), FE = TheModule->end(); - FI != FE; ++FI) { - printType(FI->getReturnType()); - printType(FI->getFunctionType()); - // Add all the function arguments - for (Function::const_arg_iterator AI = FI->arg_begin(), - AE = FI->arg_end(); AI != AE; ++AI) { - printType(AI->getType()); - } - - // Add all of the basic blocks and instructions - for (Function::const_iterator BB = FI->begin(), - E = FI->end(); BB != E; ++BB) { - printType(BB->getType()); - for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; - ++I) { - printType(I->getType()); - for (unsigned i = 0; i < I->getNumOperands(); ++i) - printType(I->getOperand(i)->getType()); - } - } - } -} - - -// printConstant - Print out a constant pool entry... -void CppWriter::printConstant(const Constant *CV) { - // First, if the constant is actually a GlobalValue (variable or function) - // or its already in the constant list then we've printed it already and we - // can just return. - if (isa<GlobalValue>(CV) || ValueNames.find(CV) != ValueNames.end()) - return; - - std::string constName(getCppName(CV)); - std::string typeName(getCppName(CV->getType())); - - if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { - std::string constValue = CI->getValue().toString(10, true); - Out << "ConstantInt* " << constName - << " = ConstantInt::get(mod->getContext(), APInt(" - << cast<IntegerType>(CI->getType())->getBitWidth() - << ", StringRef(\"" << constValue << "\"), 10));"; - } else if (isa<ConstantAggregateZero>(CV)) { - Out << "ConstantAggregateZero* " << constName - << " = ConstantAggregateZero::get(" << typeName << ");"; - } else if (isa<ConstantPointerNull>(CV)) { - Out << "ConstantPointerNull* " << constName - << " = ConstantPointerNull::get(" << typeName << ");"; - } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) { - Out << "ConstantFP* " << constName << " = "; - printCFP(CFP); - Out << ";"; - } else if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) { - Out << "std::vector<Constant*> " << constName << "_elems;"; - nl(Out); - unsigned N = CA->getNumOperands(); - for (unsigned i = 0; i < N; ++i) { - printConstant(CA->getOperand(i)); // recurse to print operands - Out << constName << "_elems.push_back(" - << getCppName(CA->getOperand(i)) << ");"; - nl(Out); - } - Out << "Constant* " << constName << " = ConstantArray::get(" - << typeName << ", " << constName << "_elems);"; - } else if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(CV)) { - Out << "std::vector<Constant*> " << constName << "_fields;"; - nl(Out); - unsigned N = CS->getNumOperands(); - for (unsigned i = 0; i < N; i++) { - printConstant(CS->getOperand(i)); - Out << constName << "_fields.push_back(" - << getCppName(CS->getOperand(i)) << ");"; - nl(Out); - } - Out << "Constant* " << constName << " = ConstantStruct::get(" - << typeName << ", " << constName << "_fields);"; - } else if (const ConstantVector *CVec = dyn_cast<ConstantVector>(CV)) { - Out << "std::vector<Constant*> " << constName << "_elems;"; - nl(Out); - unsigned N = CVec->getNumOperands(); - for (unsigned i = 0; i < N; ++i) { - printConstant(CVec->getOperand(i)); - Out << constName << "_elems.push_back(" - << getCppName(CVec->getOperand(i)) << ");"; - nl(Out); - } - Out << "Constant* " << constName << " = ConstantVector::get(" - << typeName << ", " << constName << "_elems);"; - } else if (isa<UndefValue>(CV)) { - Out << "UndefValue* " << constName << " = UndefValue::get(" - << typeName << ");"; - } else if (const ConstantDataSequential *CDS = - dyn_cast<ConstantDataSequential>(CV)) { - if (CDS->isString()) { - Out << "Constant *" << constName << - " = ConstantDataArray::getString(mod->getContext(), \""; - StringRef Str = CDS->getAsString(); - bool nullTerminate = false; - if (Str.back() == 0) { - Str = Str.drop_back(); - nullTerminate = true; - } - printEscapedString(Str); - // Determine if we want null termination or not. - if (nullTerminate) - Out << "\", true);"; - else - Out << "\", false);";// No null terminator - } else { - // TODO: Could generate more efficient code generating CDS calls instead. - Out << "std::vector<Constant*> " << constName << "_elems;"; - nl(Out); - for (unsigned i = 0; i != CDS->getNumElements(); ++i) { - Constant *Elt = CDS->getElementAsConstant(i); - printConstant(Elt); - Out << constName << "_elems.push_back(" << getCppName(Elt) << ");"; - nl(Out); - } - Out << "Constant* " << constName; - - if (isa<ArrayType>(CDS->getType())) - Out << " = ConstantArray::get("; - else - Out << " = ConstantVector::get("; - Out << typeName << ", " << constName << "_elems);"; - } - } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { - if (CE->getOpcode() == Instruction::GetElementPtr) { - Out << "std::vector<Constant*> " << constName << "_indices;"; - nl(Out); - printConstant(CE->getOperand(0)); - for (unsigned i = 1; i < CE->getNumOperands(); ++i ) { - printConstant(CE->getOperand(i)); - Out << constName << "_indices.push_back(" - << getCppName(CE->getOperand(i)) << ");"; - nl(Out); - } - Out << "Constant* " << constName - << " = ConstantExpr::getGetElementPtr(" - << getCppName(CE->getOperand(0)) << ", " - << constName << "_indices);"; - } else if (CE->isCast()) { - printConstant(CE->getOperand(0)); - Out << "Constant* " << constName << " = ConstantExpr::getCast("; - switch (CE->getOpcode()) { - default: llvm_unreachable("Invalid cast opcode"); - case Instruction::Trunc: Out << "Instruction::Trunc"; break; - case Instruction::ZExt: Out << "Instruction::ZExt"; break; - case Instruction::SExt: Out << "Instruction::SExt"; break; - case Instruction::FPTrunc: Out << "Instruction::FPTrunc"; break; - case Instruction::FPExt: Out << "Instruction::FPExt"; break; - case Instruction::FPToUI: Out << "Instruction::FPToUI"; break; - case Instruction::FPToSI: Out << "Instruction::FPToSI"; break; - case Instruction::UIToFP: Out << "Instruction::UIToFP"; break; - case Instruction::SIToFP: Out << "Instruction::SIToFP"; break; - case Instruction::PtrToInt: Out << "Instruction::PtrToInt"; break; - case Instruction::IntToPtr: Out << "Instruction::IntToPtr"; break; - case Instruction::BitCast: Out << "Instruction::BitCast"; break; - } - Out << ", " << getCppName(CE->getOperand(0)) << ", " - << getCppName(CE->getType()) << ");"; - } else { - unsigned N = CE->getNumOperands(); - for (unsigned i = 0; i < N; ++i ) { - printConstant(CE->getOperand(i)); - } - Out << "Constant* " << constName << " = ConstantExpr::"; - switch (CE->getOpcode()) { - case Instruction::Add: Out << "getAdd("; break; - case Instruction::FAdd: Out << "getFAdd("; break; - case Instruction::Sub: Out << "getSub("; break; - case Instruction::FSub: Out << "getFSub("; break; - case Instruction::Mul: Out << "getMul("; break; - case Instruction::FMul: Out << "getFMul("; break; - case Instruction::UDiv: Out << "getUDiv("; break; - case Instruction::SDiv: Out << "getSDiv("; break; - case Instruction::FDiv: Out << "getFDiv("; break; - case Instruction::URem: Out << "getURem("; break; - case Instruction::SRem: Out << "getSRem("; break; - case Instruction::FRem: Out << "getFRem("; break; - case Instruction::And: Out << "getAnd("; break; - case Instruction::Or: Out << "getOr("; break; - case Instruction::Xor: Out << "getXor("; break; - case Instruction::ICmp: - Out << "getICmp(ICmpInst::ICMP_"; - switch (CE->getPredicate()) { - case ICmpInst::ICMP_EQ: Out << "EQ"; break; - case ICmpInst::ICMP_NE: Out << "NE"; break; - case ICmpInst::ICMP_SLT: Out << "SLT"; break; - case ICmpInst::ICMP_ULT: Out << "ULT"; break; - case ICmpInst::ICMP_SGT: Out << "SGT"; break; - case ICmpInst::ICMP_UGT: Out << "UGT"; break; - case ICmpInst::ICMP_SLE: Out << "SLE"; break; - case ICmpInst::ICMP_ULE: Out << "ULE"; break; - case ICmpInst::ICMP_SGE: Out << "SGE"; break; - case ICmpInst::ICMP_UGE: Out << "UGE"; break; - default: error("Invalid ICmp Predicate"); - } - break; - case Instruction::FCmp: - Out << "getFCmp(FCmpInst::FCMP_"; - switch (CE->getPredicate()) { - case FCmpInst::FCMP_FALSE: Out << "FALSE"; break; - case FCmpInst::FCMP_ORD: Out << "ORD"; break; - case FCmpInst::FCMP_UNO: Out << "UNO"; break; - case FCmpInst::FCMP_OEQ: Out << "OEQ"; break; - case FCmpInst::FCMP_UEQ: Out << "UEQ"; break; - case FCmpInst::FCMP_ONE: Out << "ONE"; break; - case FCmpInst::FCMP_UNE: Out << "UNE"; break; - case FCmpInst::FCMP_OLT: Out << "OLT"; break; - case FCmpInst::FCMP_ULT: Out << "ULT"; break; - case FCmpInst::FCMP_OGT: Out << "OGT"; break; - case FCmpInst::FCMP_UGT: Out << "UGT"; break; - case FCmpInst::FCMP_OLE: Out << "OLE"; break; - case FCmpInst::FCMP_ULE: Out << "ULE"; break; - case FCmpInst::FCMP_OGE: Out << "OGE"; break; - case FCmpInst::FCMP_UGE: Out << "UGE"; break; - case FCmpInst::FCMP_TRUE: Out << "TRUE"; break; - default: error("Invalid FCmp Predicate"); - } - break; - case Instruction::Shl: Out << "getShl("; break; - case Instruction::LShr: Out << "getLShr("; break; - case Instruction::AShr: Out << "getAShr("; break; - case Instruction::Select: Out << "getSelect("; break; - case Instruction::ExtractElement: Out << "getExtractElement("; break; - case Instruction::InsertElement: Out << "getInsertElement("; break; - case Instruction::ShuffleVector: Out << "getShuffleVector("; break; - default: - error("Invalid constant expression"); - break; - } - Out << getCppName(CE->getOperand(0)); - for (unsigned i = 1; i < CE->getNumOperands(); ++i) - Out << ", " << getCppName(CE->getOperand(i)); - Out << ");"; - } - } else if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) { - Out << "Constant* " << constName << " = "; - Out << "BlockAddress::get(" << getOpName(BA->getBasicBlock()) << ");"; - } else { - error("Bad Constant"); - Out << "Constant* " << constName << " = 0; "; - } - nl(Out); -} - -void CppWriter::printConstants(const Module* M) { - // Traverse all the global variables looking for constant initializers - for (Module::const_global_iterator I = TheModule->global_begin(), - E = TheModule->global_end(); I != E; ++I) - if (I->hasInitializer()) - printConstant(I->getInitializer()); - - // Traverse the LLVM functions looking for constants - for (Module::const_iterator FI = TheModule->begin(), FE = TheModule->end(); - FI != FE; ++FI) { - // Add all of the basic blocks and instructions - for (Function::const_iterator BB = FI->begin(), - E = FI->end(); BB != E; ++BB) { - for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; - ++I) { - for (unsigned i = 0; i < I->getNumOperands(); ++i) { - if (Constant* C = dyn_cast<Constant>(I->getOperand(i))) { - printConstant(C); - } - } - } - } - } -} - -void CppWriter::printVariableUses(const GlobalVariable *GV) { - nl(Out) << "// Type Definitions"; - nl(Out); - printType(GV->getType()); - if (GV->hasInitializer()) { - const Constant *Init = GV->getInitializer(); - printType(Init->getType()); - if (const Function *F = dyn_cast<Function>(Init)) { - nl(Out)<< "/ Function Declarations"; nl(Out); - printFunctionHead(F); - } else if (const GlobalVariable* gv = dyn_cast<GlobalVariable>(Init)) { - nl(Out) << "// Global Variable Declarations"; nl(Out); - printVariableHead(gv); - - nl(Out) << "// Global Variable Definitions"; nl(Out); - printVariableBody(gv); - } else { - nl(Out) << "// Constant Definitions"; nl(Out); - printConstant(Init); - } - } -} - -void CppWriter::printVariableHead(const GlobalVariable *GV) { - nl(Out) << "GlobalVariable* " << getCppName(GV); - if (is_inline) { - Out << " = mod->getGlobalVariable(mod->getContext(), "; - printEscapedString(GV->getName()); - Out << ", " << getCppName(GV->getType()->getElementType()) << ",true)"; - nl(Out) << "if (!" << getCppName(GV) << ") {"; - in(); nl(Out) << getCppName(GV); - } - Out << " = new GlobalVariable(/*Module=*/*mod, "; - nl(Out) << "/*Type=*/"; - printCppName(GV->getType()->getElementType()); - Out << ","; - nl(Out) << "/*isConstant=*/" << (GV->isConstant()?"true":"false"); - Out << ","; - nl(Out) << "/*Linkage=*/"; - printLinkageType(GV->getLinkage()); - Out << ","; - nl(Out) << "/*Initializer=*/0, "; - if (GV->hasInitializer()) { - Out << "// has initializer, specified below"; - } - nl(Out) << "/*Name=*/\""; - printEscapedString(GV->getName()); - Out << "\");"; - nl(Out); - - if (GV->hasSection()) { - printCppName(GV); - Out << "->setSection(\""; - printEscapedString(GV->getSection()); - Out << "\");"; - nl(Out); - } - if (GV->getAlignment()) { - printCppName(GV); - Out << "->setAlignment(" << GV->getAlignment() << ");"; - nl(Out); - } - if (GV->getVisibility() != GlobalValue::DefaultVisibility) { - printCppName(GV); - Out << "->setVisibility("; - printVisibilityType(GV->getVisibility()); - Out << ");"; - nl(Out); - } - if (GV->getDLLStorageClass() != GlobalValue::DefaultStorageClass) { - printCppName(GV); - Out << "->setDLLStorageClass("; - printDLLStorageClassType(GV->getDLLStorageClass()); - Out << ");"; - nl(Out); - } - if (GV->isThreadLocal()) { - printCppName(GV); - Out << "->setThreadLocalMode("; - printThreadLocalMode(GV->getThreadLocalMode()); - Out << ");"; - nl(Out); - } - if (is_inline) { - out(); Out << "}"; nl(Out); - } -} - -void CppWriter::printVariableBody(const GlobalVariable *GV) { - if (GV->hasInitializer()) { - printCppName(GV); - Out << "->setInitializer("; - Out << getCppName(GV->getInitializer()) << ");"; - nl(Out); - } -} - -std::string CppWriter::getOpName(const Value* V) { - if (!isa<Instruction>(V) || DefinedValues.find(V) != DefinedValues.end()) - return getCppName(V); - - // See if its alread in the map of forward references, if so just return the - // name we already set up for it - ForwardRefMap::const_iterator I = ForwardRefs.find(V); - if (I != ForwardRefs.end()) - return I->second; - - // This is a new forward reference. Generate a unique name for it - std::string result(std::string("fwdref_") + utostr(uniqueNum++)); - - // Yes, this is a hack. An Argument is the smallest instantiable value that - // we can make as a placeholder for the real value. We'll replace these - // Argument instances later. - Out << "Argument* " << result << " = new Argument(" - << getCppName(V->getType()) << ");"; - nl(Out); - ForwardRefs[V] = result; - return result; -} - -static StringRef ConvertAtomicOrdering(AtomicOrdering Ordering) { - switch (Ordering) { - case NotAtomic: return "NotAtomic"; - case Unordered: return "Unordered"; - case Monotonic: return "Monotonic"; - case Acquire: return "Acquire"; - case Release: return "Release"; - case AcquireRelease: return "AcquireRelease"; - case SequentiallyConsistent: return "SequentiallyConsistent"; - } - llvm_unreachable("Unknown ordering"); -} - -static StringRef ConvertAtomicSynchScope(SynchronizationScope SynchScope) { - switch (SynchScope) { - case SingleThread: return "SingleThread"; - case CrossThread: return "CrossThread"; - } - llvm_unreachable("Unknown synch scope"); -} - -// printInstruction - This member is called for each Instruction in a function. -void CppWriter::printInstruction(const Instruction *I, - const std::string& bbname) { - std::string iName(getCppName(I)); - - // Before we emit this instruction, we need to take care of generating any - // forward references. So, we get the names of all the operands in advance - const unsigned Ops(I->getNumOperands()); - std::string* opNames = new std::string[Ops]; - for (unsigned i = 0; i < Ops; i++) - opNames[i] = getOpName(I->getOperand(i)); - - switch (I->getOpcode()) { - default: - error("Invalid instruction"); - break; - - case Instruction::Ret: { - const ReturnInst* ret = cast<ReturnInst>(I); - Out << "ReturnInst::Create(mod->getContext(), " - << (ret->getReturnValue() ? opNames[0] + ", " : "") << bbname << ");"; - break; - } - case Instruction::Br: { - const BranchInst* br = cast<BranchInst>(I); - Out << "BranchInst::Create(" ; - if (br->getNumOperands() == 3) { - Out << opNames[2] << ", " - << opNames[1] << ", " - << opNames[0] << ", "; - - } else if (br->getNumOperands() == 1) { - Out << opNames[0] << ", "; - } else { - error("Branch with 2 operands?"); - } - Out << bbname << ");"; - break; - } - case Instruction::Switch: { - const SwitchInst *SI = cast<SwitchInst>(I); - Out << "SwitchInst* " << iName << " = SwitchInst::Create(" - << getOpName(SI->getCondition()) << ", " - << getOpName(SI->getDefaultDest()) << ", " - << SI->getNumCases() << ", " << bbname << ");"; - nl(Out); - for (SwitchInst::ConstCaseIt i = SI->case_begin(), e = SI->case_end(); - i != e; ++i) { - const ConstantInt* CaseVal = i.getCaseValue(); - const BasicBlock *BB = i.getCaseSuccessor(); - Out << iName << "->addCase(" - << getOpName(CaseVal) << ", " - << getOpName(BB) << ");"; - nl(Out); - } - break; - } - case Instruction::IndirectBr: { - const IndirectBrInst *IBI = cast<IndirectBrInst>(I); - Out << "IndirectBrInst *" << iName << " = IndirectBrInst::Create(" - << opNames[0] << ", " << IBI->getNumDestinations() << ");"; - nl(Out); - for (unsigned i = 1; i != IBI->getNumOperands(); ++i) { - Out << iName << "->addDestination(" << opNames[i] << ");"; - nl(Out); - } - break; - } - case Instruction::Resume: { - Out << "ResumeInst::Create(" << opNames[0] << ", " << bbname << ");"; - break; - } - case Instruction::Invoke: { - const InvokeInst* inv = cast<InvokeInst>(I); - Out << "std::vector<Value*> " << iName << "_params;"; - nl(Out); - for (unsigned i = 0; i < inv->getNumArgOperands(); ++i) { - Out << iName << "_params.push_back(" - << getOpName(inv->getArgOperand(i)) << ");"; - nl(Out); - } - // FIXME: This shouldn't use magic numbers -3, -2, and -1. - Out << "InvokeInst *" << iName << " = InvokeInst::Create(" - << getOpName(inv->getCalledValue()) << ", " - << getOpName(inv->getNormalDest()) << ", " - << getOpName(inv->getUnwindDest()) << ", " - << iName << "_params, \""; - printEscapedString(inv->getName()); - Out << "\", " << bbname << ");"; - nl(Out) << iName << "->setCallingConv("; - printCallingConv(inv->getCallingConv()); - Out << ");"; - printAttributes(inv->getAttributes(), iName); - Out << iName << "->setAttributes(" << iName << "_PAL);"; - nl(Out); - break; - } - case Instruction::Unreachable: { - Out << "new UnreachableInst(" - << "mod->getContext(), " - << bbname << ");"; - break; - } - case Instruction::Add: - case Instruction::FAdd: - case Instruction::Sub: - case Instruction::FSub: - case Instruction::Mul: - case Instruction::FMul: - case Instruction::UDiv: - case Instruction::SDiv: - case Instruction::FDiv: - case Instruction::URem: - case Instruction::SRem: - case Instruction::FRem: - case Instruction::And: - case Instruction::Or: - case Instruction::Xor: - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr:{ - Out << "BinaryOperator* " << iName << " = BinaryOperator::Create("; - switch (I->getOpcode()) { - case Instruction::Add: Out << "Instruction::Add"; break; - case Instruction::FAdd: Out << "Instruction::FAdd"; break; - case Instruction::Sub: Out << "Instruction::Sub"; break; - case Instruction::FSub: Out << "Instruction::FSub"; break; - case Instruction::Mul: Out << "Instruction::Mul"; break; - case Instruction::FMul: Out << "Instruction::FMul"; break; - case Instruction::UDiv:Out << "Instruction::UDiv"; break; - case Instruction::SDiv:Out << "Instruction::SDiv"; break; - case Instruction::FDiv:Out << "Instruction::FDiv"; break; - case Instruction::URem:Out << "Instruction::URem"; break; - case Instruction::SRem:Out << "Instruction::SRem"; break; - case Instruction::FRem:Out << "Instruction::FRem"; break; - case Instruction::And: Out << "Instruction::And"; break; - case Instruction::Or: Out << "Instruction::Or"; break; - case Instruction::Xor: Out << "Instruction::Xor"; break; - case Instruction::Shl: Out << "Instruction::Shl"; break; - case Instruction::LShr:Out << "Instruction::LShr"; break; - case Instruction::AShr:Out << "Instruction::AShr"; break; - default: Out << "Instruction::BadOpCode"; break; - } - Out << ", " << opNames[0] << ", " << opNames[1] << ", \""; - printEscapedString(I->getName()); - Out << "\", " << bbname << ");"; - break; - } - case Instruction::FCmp: { - Out << "FCmpInst* " << iName << " = new FCmpInst(*" << bbname << ", "; - switch (cast<FCmpInst>(I)->getPredicate()) { - case FCmpInst::FCMP_FALSE: Out << "FCmpInst::FCMP_FALSE"; break; - case FCmpInst::FCMP_OEQ : Out << "FCmpInst::FCMP_OEQ"; break; - case FCmpInst::FCMP_OGT : Out << "FCmpInst::FCMP_OGT"; break; - case FCmpInst::FCMP_OGE : Out << "FCmpInst::FCMP_OGE"; break; - case FCmpInst::FCMP_OLT : Out << "FCmpInst::FCMP_OLT"; break; - case FCmpInst::FCMP_OLE : Out << "FCmpInst::FCMP_OLE"; break; - case FCmpInst::FCMP_ONE : Out << "FCmpInst::FCMP_ONE"; break; - case FCmpInst::FCMP_ORD : Out << "FCmpInst::FCMP_ORD"; break; - case FCmpInst::FCMP_UNO : Out << "FCmpInst::FCMP_UNO"; break; - case FCmpInst::FCMP_UEQ : Out << "FCmpInst::FCMP_UEQ"; break; - case FCmpInst::FCMP_UGT : Out << "FCmpInst::FCMP_UGT"; break; - case FCmpInst::FCMP_UGE : Out << "FCmpInst::FCMP_UGE"; break; - case FCmpInst::FCMP_ULT : Out << "FCmpInst::FCMP_ULT"; break; - case FCmpInst::FCMP_ULE : Out << "FCmpInst::FCMP_ULE"; break; - case FCmpInst::FCMP_UNE : Out << "FCmpInst::FCMP_UNE"; break; - case FCmpInst::FCMP_TRUE : Out << "FCmpInst::FCMP_TRUE"; break; - default: Out << "FCmpInst::BAD_ICMP_PREDICATE"; break; - } - Out << ", " << opNames[0] << ", " << opNames[1] << ", \""; - printEscapedString(I->getName()); - Out << "\");"; - break; - } - case Instruction::ICmp: { - Out << "ICmpInst* " << iName << " = new ICmpInst(*" << bbname << ", "; - switch (cast<ICmpInst>(I)->getPredicate()) { - case ICmpInst::ICMP_EQ: Out << "ICmpInst::ICMP_EQ"; break; - case ICmpInst::ICMP_NE: Out << "ICmpInst::ICMP_NE"; break; - case ICmpInst::ICMP_ULE: Out << "ICmpInst::ICMP_ULE"; break; - case ICmpInst::ICMP_SLE: Out << "ICmpInst::ICMP_SLE"; break; - case ICmpInst::ICMP_UGE: Out << "ICmpInst::ICMP_UGE"; break; - case ICmpInst::ICMP_SGE: Out << "ICmpInst::ICMP_SGE"; break; - case ICmpInst::ICMP_ULT: Out << "ICmpInst::ICMP_ULT"; break; - case ICmpInst::ICMP_SLT: Out << "ICmpInst::ICMP_SLT"; break; - case ICmpInst::ICMP_UGT: Out << "ICmpInst::ICMP_UGT"; break; - case ICmpInst::ICMP_SGT: Out << "ICmpInst::ICMP_SGT"; break; - default: Out << "ICmpInst::BAD_ICMP_PREDICATE"; break; - } - Out << ", " << opNames[0] << ", " << opNames[1] << ", \""; - printEscapedString(I->getName()); - Out << "\");"; - break; - } - case Instruction::Alloca: { - const AllocaInst* allocaI = cast<AllocaInst>(I); - Out << "AllocaInst* " << iName << " = new AllocaInst(" - << getCppName(allocaI->getAllocatedType()) << ", "; - if (allocaI->isArrayAllocation()) - Out << opNames[0] << ", "; - Out << "\""; - printEscapedString(allocaI->getName()); - Out << "\", " << bbname << ");"; - if (allocaI->getAlignment()) - nl(Out) << iName << "->setAlignment(" - << allocaI->getAlignment() << ");"; - break; - } - case Instruction::Load: { - const LoadInst* load = cast<LoadInst>(I); - Out << "LoadInst* " << iName << " = new LoadInst(" - << opNames[0] << ", \""; - printEscapedString(load->getName()); - Out << "\", " << (load->isVolatile() ? "true" : "false" ) - << ", " << bbname << ");"; - if (load->getAlignment()) - nl(Out) << iName << "->setAlignment(" - << load->getAlignment() << ");"; - if (load->isAtomic()) { - StringRef Ordering = ConvertAtomicOrdering(load->getOrdering()); - StringRef CrossThread = ConvertAtomicSynchScope(load->getSynchScope()); - nl(Out) << iName << "->setAtomic(" - << Ordering << ", " << CrossThread << ");"; - } - break; - } - case Instruction::Store: { - const StoreInst* store = cast<StoreInst>(I); - Out << "StoreInst* " << iName << " = new StoreInst(" - << opNames[0] << ", " - << opNames[1] << ", " - << (store->isVolatile() ? "true" : "false") - << ", " << bbname << ");"; - if (store->getAlignment()) - nl(Out) << iName << "->setAlignment(" - << store->getAlignment() << ");"; - if (store->isAtomic()) { - StringRef Ordering = ConvertAtomicOrdering(store->getOrdering()); - StringRef CrossThread = ConvertAtomicSynchScope(store->getSynchScope()); - nl(Out) << iName << "->setAtomic(" - << Ordering << ", " << CrossThread << ");"; - } - break; - } - case Instruction::GetElementPtr: { - const GetElementPtrInst* gep = cast<GetElementPtrInst>(I); - Out << "GetElementPtrInst* " << iName << " = GetElementPtrInst::Create(" - << getCppName(gep->getSourceElementType()) << ", " << opNames[0] << ", {"; - in(); - for (unsigned i = 1; i < gep->getNumOperands(); ++i ) { - if (i != 1) { - Out << ", "; - } - nl(Out); - Out << opNames[i]; - } - out(); - nl(Out) << "}, \""; - printEscapedString(gep->getName()); - Out << "\", " << bbname << ");"; - break; - } - case Instruction::PHI: { - const PHINode* phi = cast<PHINode>(I); - - Out << "PHINode* " << iName << " = PHINode::Create(" - << getCppName(phi->getType()) << ", " - << phi->getNumIncomingValues() << ", \""; - printEscapedString(phi->getName()); - Out << "\", " << bbname << ");"; - nl(Out); - for (unsigned i = 0; i < phi->getNumIncomingValues(); ++i) { - Out << iName << "->addIncoming(" - << opNames[PHINode::getOperandNumForIncomingValue(i)] << ", " - << getOpName(phi->getIncomingBlock(i)) << ");"; - nl(Out); - } - break; - } - case Instruction::Trunc: - case Instruction::ZExt: - case Instruction::SExt: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::FPToUI: - case Instruction::FPToSI: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::PtrToInt: - case Instruction::IntToPtr: - case Instruction::BitCast: { - const CastInst* cst = cast<CastInst>(I); - Out << "CastInst* " << iName << " = new "; - switch (I->getOpcode()) { - case Instruction::Trunc: Out << "TruncInst"; break; - case Instruction::ZExt: Out << "ZExtInst"; break; - case Instruction::SExt: Out << "SExtInst"; break; - case Instruction::FPTrunc: Out << "FPTruncInst"; break; - case Instruction::FPExt: Out << "FPExtInst"; break; - case Instruction::FPToUI: Out << "FPToUIInst"; break; - case Instruction::FPToSI: Out << "FPToSIInst"; break; - case Instruction::UIToFP: Out << "UIToFPInst"; break; - case Instruction::SIToFP: Out << "SIToFPInst"; break; - case Instruction::PtrToInt: Out << "PtrToIntInst"; break; - case Instruction::IntToPtr: Out << "IntToPtrInst"; break; - case Instruction::BitCast: Out << "BitCastInst"; break; - default: llvm_unreachable("Unreachable"); - } - Out << "(" << opNames[0] << ", " - << getCppName(cst->getType()) << ", \""; - printEscapedString(cst->getName()); - Out << "\", " << bbname << ");"; - break; - } - case Instruction::Call: { - const CallInst* call = cast<CallInst>(I); - if (const InlineAsm* ila = dyn_cast<InlineAsm>(call->getCalledValue())) { - Out << "InlineAsm* " << getCppName(ila) << " = InlineAsm::get(" - << getCppName(ila->getFunctionType()) << ", \"" - << ila->getAsmString() << "\", \"" - << ila->getConstraintString() << "\"," - << (ila->hasSideEffects() ? "true" : "false") << ");"; - nl(Out); - } - if (call->getNumArgOperands() > 1) { - Out << "std::vector<Value*> " << iName << "_params;"; - nl(Out); - for (unsigned i = 0; i < call->getNumArgOperands(); ++i) { - Out << iName << "_params.push_back(" << opNames[i] << ");"; - nl(Out); - } - Out << "CallInst* " << iName << " = CallInst::Create(" - << opNames[call->getNumArgOperands()] << ", " - << iName << "_params, \""; - } else if (call->getNumArgOperands() == 1) { - Out << "CallInst* " << iName << " = CallInst::Create(" - << opNames[call->getNumArgOperands()] << ", " << opNames[0] << ", \""; - } else { - Out << "CallInst* " << iName << " = CallInst::Create(" - << opNames[call->getNumArgOperands()] << ", \""; - } - printEscapedString(call->getName()); - Out << "\", " << bbname << ");"; - nl(Out) << iName << "->setCallingConv("; - printCallingConv(call->getCallingConv()); - Out << ");"; - nl(Out) << iName << "->setTailCall(" - << (call->isTailCall() ? "true" : "false"); - Out << ");"; - nl(Out); - printAttributes(call->getAttributes(), iName); - Out << iName << "->setAttributes(" << iName << "_PAL);"; - nl(Out); - break; - } - case Instruction::Select: { - const SelectInst* sel = cast<SelectInst>(I); - Out << "SelectInst* " << getCppName(sel) << " = SelectInst::Create("; - Out << opNames[0] << ", " << opNames[1] << ", " << opNames[2] << ", \""; - printEscapedString(sel->getName()); - Out << "\", " << bbname << ");"; - break; - } - case Instruction::UserOp1: - /// FALL THROUGH - case Instruction::UserOp2: { - /// FIXME: What should be done here? - break; - } - case Instruction::VAArg: { - const VAArgInst* va = cast<VAArgInst>(I); - Out << "VAArgInst* " << getCppName(va) << " = new VAArgInst(" - << opNames[0] << ", " << getCppName(va->getType()) << ", \""; - printEscapedString(va->getName()); - Out << "\", " << bbname << ");"; - break; - } - case Instruction::ExtractElement: { - const ExtractElementInst* eei = cast<ExtractElementInst>(I); - Out << "ExtractElementInst* " << getCppName(eei) - << " = new ExtractElementInst(" << opNames[0] - << ", " << opNames[1] << ", \""; - printEscapedString(eei->getName()); - Out << "\", " << bbname << ");"; - break; - } - case Instruction::InsertElement: { - const InsertElementInst* iei = cast<InsertElementInst>(I); - Out << "InsertElementInst* " << getCppName(iei) - << " = InsertElementInst::Create(" << opNames[0] - << ", " << opNames[1] << ", " << opNames[2] << ", \""; - printEscapedString(iei->getName()); - Out << "\", " << bbname << ");"; - break; - } - case Instruction::ShuffleVector: { - const ShuffleVectorInst* svi = cast<ShuffleVectorInst>(I); - Out << "ShuffleVectorInst* " << getCppName(svi) - << " = new ShuffleVectorInst(" << opNames[0] - << ", " << opNames[1] << ", " << opNames[2] << ", \""; - printEscapedString(svi->getName()); - Out << "\", " << bbname << ");"; - break; - } - case Instruction::ExtractValue: { - const ExtractValueInst *evi = cast<ExtractValueInst>(I); - Out << "std::vector<unsigned> " << iName << "_indices;"; - nl(Out); - for (unsigned i = 0; i < evi->getNumIndices(); ++i) { - Out << iName << "_indices.push_back(" - << evi->idx_begin()[i] << ");"; - nl(Out); - } - Out << "ExtractValueInst* " << getCppName(evi) - << " = ExtractValueInst::Create(" << opNames[0] - << ", " - << iName << "_indices, \""; - printEscapedString(evi->getName()); - Out << "\", " << bbname << ");"; - break; - } - case Instruction::InsertValue: { - const InsertValueInst *ivi = cast<InsertValueInst>(I); - Out << "std::vector<unsigned> " << iName << "_indices;"; - nl(Out); - for (unsigned i = 0; i < ivi->getNumIndices(); ++i) { - Out << iName << "_indices.push_back(" - << ivi->idx_begin()[i] << ");"; - nl(Out); - } - Out << "InsertValueInst* " << getCppName(ivi) - << " = InsertValueInst::Create(" << opNames[0] - << ", " << opNames[1] << ", " - << iName << "_indices, \""; - printEscapedString(ivi->getName()); - Out << "\", " << bbname << ");"; - break; - } - case Instruction::Fence: { - const FenceInst *fi = cast<FenceInst>(I); - StringRef Ordering = ConvertAtomicOrdering(fi->getOrdering()); - StringRef CrossThread = ConvertAtomicSynchScope(fi->getSynchScope()); - Out << "FenceInst* " << iName - << " = new FenceInst(mod->getContext(), " - << Ordering << ", " << CrossThread << ", " << bbname - << ");"; - break; - } - case Instruction::AtomicCmpXchg: { - const AtomicCmpXchgInst *cxi = cast<AtomicCmpXchgInst>(I); - StringRef SuccessOrdering = - ConvertAtomicOrdering(cxi->getSuccessOrdering()); - StringRef FailureOrdering = - ConvertAtomicOrdering(cxi->getFailureOrdering()); - StringRef CrossThread = ConvertAtomicSynchScope(cxi->getSynchScope()); - Out << "AtomicCmpXchgInst* " << iName - << " = new AtomicCmpXchgInst(" - << opNames[0] << ", " << opNames[1] << ", " << opNames[2] << ", " - << SuccessOrdering << ", " << FailureOrdering << ", " - << CrossThread << ", " << bbname - << ");"; - nl(Out) << iName << "->setName(\""; - printEscapedString(cxi->getName()); - Out << "\");"; - nl(Out) << iName << "->setVolatile(" - << (cxi->isVolatile() ? "true" : "false") << ");"; - nl(Out) << iName << "->setWeak(" - << (cxi->isWeak() ? "true" : "false") << ");"; - break; - } - case Instruction::AtomicRMW: { - const AtomicRMWInst *rmwi = cast<AtomicRMWInst>(I); - StringRef Ordering = ConvertAtomicOrdering(rmwi->getOrdering()); - StringRef CrossThread = ConvertAtomicSynchScope(rmwi->getSynchScope()); - StringRef Operation; - switch (rmwi->getOperation()) { - case AtomicRMWInst::Xchg: Operation = "AtomicRMWInst::Xchg"; break; - case AtomicRMWInst::Add: Operation = "AtomicRMWInst::Add"; break; - case AtomicRMWInst::Sub: Operation = "AtomicRMWInst::Sub"; break; - case AtomicRMWInst::And: Operation = "AtomicRMWInst::And"; break; - case AtomicRMWInst::Nand: Operation = "AtomicRMWInst::Nand"; break; - case AtomicRMWInst::Or: Operation = "AtomicRMWInst::Or"; break; - case AtomicRMWInst::Xor: Operation = "AtomicRMWInst::Xor"; break; - case AtomicRMWInst::Max: Operation = "AtomicRMWInst::Max"; break; - case AtomicRMWInst::Min: Operation = "AtomicRMWInst::Min"; break; - case AtomicRMWInst::UMax: Operation = "AtomicRMWInst::UMax"; break; - case AtomicRMWInst::UMin: Operation = "AtomicRMWInst::UMin"; break; - case AtomicRMWInst::BAD_BINOP: llvm_unreachable("Bad atomic operation"); - } - Out << "AtomicRMWInst* " << iName - << " = new AtomicRMWInst(" - << Operation << ", " - << opNames[0] << ", " << opNames[1] << ", " - << Ordering << ", " << CrossThread << ", " << bbname - << ");"; - nl(Out) << iName << "->setName(\""; - printEscapedString(rmwi->getName()); - Out << "\");"; - nl(Out) << iName << "->setVolatile(" - << (rmwi->isVolatile() ? "true" : "false") << ");"; - break; - } - case Instruction::LandingPad: { - const LandingPadInst *lpi = cast<LandingPadInst>(I); - Out << "LandingPadInst* " << iName << " = LandingPadInst::Create("; - printCppName(lpi->getType()); - Out << ", " << opNames[0] << ", " << lpi->getNumClauses() << ", \""; - printEscapedString(lpi->getName()); - Out << "\", " << bbname << ");"; - nl(Out) << iName << "->setCleanup(" - << (lpi->isCleanup() ? "true" : "false") - << ");"; - for (unsigned i = 0, e = lpi->getNumClauses(); i != e; ++i) - nl(Out) << iName << "->addClause(" << opNames[i+1] << ");"; - break; - } - } - DefinedValues.insert(I); - nl(Out); - delete [] opNames; -} - -// Print out the types, constants and declarations needed by one function -void CppWriter::printFunctionUses(const Function* F) { - nl(Out) << "// Type Definitions"; nl(Out); - if (!is_inline) { - // Print the function's return type - printType(F->getReturnType()); - - // Print the function's function type - printType(F->getFunctionType()); - - // Print the types of each of the function's arguments - for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); - AI != AE; ++AI) { - printType(AI->getType()); - } - } - - // Print type definitions for every type referenced by an instruction and - // make a note of any global values or constants that are referenced - SmallPtrSet<GlobalValue*,64> gvs; - SmallPtrSet<Constant*,64> consts; - for (Function::const_iterator BB = F->begin(), BE = F->end(); - BB != BE; ++BB){ - for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); - I != E; ++I) { - // Print the type of the instruction itself - printType(I->getType()); - - // Print the type of each of the instruction's operands - for (unsigned i = 0; i < I->getNumOperands(); ++i) { - Value* operand = I->getOperand(i); - printType(operand->getType()); - - // If the operand references a GVal or Constant, make a note of it - if (GlobalValue* GV = dyn_cast<GlobalValue>(operand)) { - gvs.insert(GV); - if (GenerationType != GenFunction) - if (GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) - if (GVar->hasInitializer()) - consts.insert(GVar->getInitializer()); - } else if (Constant* C = dyn_cast<Constant>(operand)) { - consts.insert(C); - for (Value* operand : C->operands()) { - // If the operand references a GVal or Constant, make a note of it - printType(operand->getType()); - if (GlobalValue* GV = dyn_cast<GlobalValue>(operand)) { - gvs.insert(GV); - if (GenerationType != GenFunction) - if (GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) - if (GVar->hasInitializer()) - consts.insert(GVar->getInitializer()); - } - } - } - } - } - } - - // Print the function declarations for any functions encountered - nl(Out) << "// Function Declarations"; nl(Out); - for (auto *GV : gvs) { - if (Function *Fun = dyn_cast<Function>(GV)) { - if (!is_inline || Fun != F) - printFunctionHead(Fun); - } - } - - // Print the global variable declarations for any variables encountered - nl(Out) << "// Global Variable Declarations"; nl(Out); - for (auto *GV : gvs) { - if (GlobalVariable *F = dyn_cast<GlobalVariable>(GV)) - printVariableHead(F); - } - - // Print the constants found - nl(Out) << "// Constant Definitions"; nl(Out); - for (const auto *C : consts) { - printConstant(C); - } - - // Process the global variables definitions now that all the constants have - // been emitted. These definitions just couple the gvars with their constant - // initializers. - if (GenerationType != GenFunction) { - nl(Out) << "// Global Variable Definitions"; nl(Out); - for (auto *GV : gvs) { - if (GlobalVariable *Var = dyn_cast<GlobalVariable>(GV)) - printVariableBody(Var); - } - } -} - -void CppWriter::printFunctionHead(const Function* F) { - nl(Out) << "Function* " << getCppName(F); - Out << " = mod->getFunction(\""; - printEscapedString(F->getName()); - Out << "\");"; - nl(Out) << "if (!" << getCppName(F) << ") {"; - nl(Out) << getCppName(F); - - Out<< " = Function::Create("; - nl(Out,1) << "/*Type=*/" << getCppName(F->getFunctionType()) << ","; - nl(Out) << "/*Linkage=*/"; - printLinkageType(F->getLinkage()); - Out << ","; - nl(Out) << "/*Name=*/\""; - printEscapedString(F->getName()); - Out << "\", mod); " << (F->isDeclaration()? "// (external, no body)" : ""); - nl(Out,-1); - printCppName(F); - Out << "->setCallingConv("; - printCallingConv(F->getCallingConv()); - Out << ");"; - nl(Out); - if (F->hasSection()) { - printCppName(F); - Out << "->setSection(\"" << F->getSection() << "\");"; - nl(Out); - } - if (F->getAlignment()) { - printCppName(F); - Out << "->setAlignment(" << F->getAlignment() << ");"; - nl(Out); - } - if (F->getVisibility() != GlobalValue::DefaultVisibility) { - printCppName(F); - Out << "->setVisibility("; - printVisibilityType(F->getVisibility()); - Out << ");"; - nl(Out); - } - if (F->getDLLStorageClass() != GlobalValue::DefaultStorageClass) { - printCppName(F); - Out << "->setDLLStorageClass("; - printDLLStorageClassType(F->getDLLStorageClass()); - Out << ");"; - nl(Out); - } - if (F->hasGC()) { - printCppName(F); - Out << "->setGC(\"" << F->getGC() << "\");"; - nl(Out); - } - Out << "}"; - nl(Out); - printAttributes(F->getAttributes(), getCppName(F)); - printCppName(F); - Out << "->setAttributes(" << getCppName(F) << "_PAL);"; - nl(Out); -} - -void CppWriter::printFunctionBody(const Function *F) { - if (F->isDeclaration()) - return; // external functions have no bodies. - - // Clear the DefinedValues and ForwardRefs maps because we can't have - // cross-function forward refs - ForwardRefs.clear(); - DefinedValues.clear(); - - // Create all the argument values - if (!is_inline) { - if (!F->arg_empty()) { - Out << "Function::arg_iterator args = " << getCppName(F) - << "->arg_begin();"; - nl(Out); - } - for (const Argument &AI : F->args()) { - Out << "Value* " << getCppName(&AI) << " = args++;"; - nl(Out); - if (AI.hasName()) { - Out << getCppName(&AI) << "->setName(\""; - printEscapedString(AI.getName()); - Out << "\");"; - nl(Out); - } - } - } - - // Create all the basic blocks - nl(Out); - for (const BasicBlock &BI : *F) { - std::string bbname(getCppName(&BI)); - Out << "BasicBlock* " << bbname << - " = BasicBlock::Create(mod->getContext(), \""; - if (BI.hasName()) - printEscapedString(BI.getName()); - Out << "\"," << getCppName(BI.getParent()) << ",0);"; - nl(Out); - } - - // Output all of its basic blocks... for the function - for (const BasicBlock &BI : *F) { - std::string bbname(getCppName(&BI)); - nl(Out) << "// Block " << BI.getName() << " (" << bbname << ")"; - nl(Out); - - // Output all of the instructions in the basic block... - for (const Instruction &I : BI) - printInstruction(&I, bbname); - } - - // Loop over the ForwardRefs and resolve them now that all instructions - // are generated. - if (!ForwardRefs.empty()) { - nl(Out) << "// Resolve Forward References"; - nl(Out); - } - - while (!ForwardRefs.empty()) { - ForwardRefMap::iterator I = ForwardRefs.begin(); - Out << I->second << "->replaceAllUsesWith(" - << getCppName(I->first) << "); delete " << I->second << ";"; - nl(Out); - ForwardRefs.erase(I); - } -} - -void CppWriter::printInline(const std::string& fname, - const std::string& func) { - const Function* F = TheModule->getFunction(func); - if (!F) { - error(std::string("Function '") + func + "' not found in input module"); - return; - } - if (F->isDeclaration()) { - error(std::string("Function '") + func + "' is external!"); - return; - } - nl(Out) << "BasicBlock* " << fname << "(Module* mod, Function *" - << getCppName(F); - unsigned arg_count = 1; - for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); - AI != AE; ++AI) { - Out << ", Value* arg_" << arg_count++; - } - Out << ") {"; - nl(Out); - is_inline = true; - printFunctionUses(F); - printFunctionBody(F); - is_inline = false; - Out << "return " << getCppName(&F->front()) << ";"; - nl(Out) << "}"; - nl(Out); -} - -void CppWriter::printModuleBody() { - // Print out all the type definitions - nl(Out) << "// Type Definitions"; nl(Out); - printTypes(TheModule); - - // Functions can call each other and global variables can reference them so - // define all the functions first before emitting their function bodies. - nl(Out) << "// Function Declarations"; nl(Out); - for (const Function &I : *TheModule) - printFunctionHead(&I); - - // Process the global variables declarations. We can't initialze them until - // after the constants are printed so just print a header for each global - nl(Out) << "// Global Variable Declarations\n"; nl(Out); - for (const GlobalVariable &I : TheModule->globals()) - printVariableHead(&I); - - // Print out all the constants definitions. Constants don't recurse except - // through GlobalValues. All GlobalValues have been declared at this point - // so we can proceed to generate the constants. - nl(Out) << "// Constant Definitions"; nl(Out); - printConstants(TheModule); - - // Process the global variables definitions now that all the constants have - // been emitted. These definitions just couple the gvars with their constant - // initializers. - nl(Out) << "// Global Variable Definitions"; nl(Out); - for (const GlobalVariable &I : TheModule->globals()) - printVariableBody(&I); - - // Finally, we can safely put out all of the function bodies. - nl(Out) << "// Function Definitions"; nl(Out); - for (const Function &I : *TheModule) { - if (!I.isDeclaration()) { - nl(Out) << "// Function: " << I.getName() << " (" << getCppName(&I) - << ")"; - nl(Out) << "{"; - nl(Out,1); - printFunctionBody(&I); - nl(Out,-1) << "}"; - nl(Out); - } - } -} - -void CppWriter::printProgram(const std::string& fname, - const std::string& mName) { - Out << "#include <llvm/Pass.h>\n"; - - Out << "#include <llvm/ADT/SmallVector.h>\n"; - Out << "#include <llvm/Analysis/Verifier.h>\n"; - Out << "#include <llvm/IR/BasicBlock.h>\n"; - Out << "#include <llvm/IR/CallingConv.h>\n"; - Out << "#include <llvm/IR/Constants.h>\n"; - Out << "#include <llvm/IR/DerivedTypes.h>\n"; - Out << "#include <llvm/IR/Function.h>\n"; - Out << "#include <llvm/IR/GlobalVariable.h>\n"; - Out << "#include <llvm/IR/IRPrintingPasses.h>\n"; - Out << "#include <llvm/IR/InlineAsm.h>\n"; - Out << "#include <llvm/IR/Instructions.h>\n"; - Out << "#include <llvm/IR/LLVMContext.h>\n"; - Out << "#include <llvm/IR/LegacyPassManager.h>\n"; - Out << "#include <llvm/IR/Module.h>\n"; - Out << "#include <llvm/Support/FormattedStream.h>\n"; - Out << "#include <llvm/Support/MathExtras.h>\n"; - Out << "#include <algorithm>\n"; - Out << "using namespace llvm;\n\n"; - Out << "Module* " << fname << "();\n\n"; - Out << "int main(int argc, char**argv) {\n"; - Out << " Module* Mod = " << fname << "();\n"; - Out << " verifyModule(*Mod, PrintMessageAction);\n"; - Out << " PassManager PM;\n"; - Out << " PM.add(createPrintModulePass(&outs()));\n"; - Out << " PM.run(*Mod);\n"; - Out << " return 0;\n"; - Out << "}\n\n"; - printModule(fname,mName); -} - -void CppWriter::printModule(const std::string& fname, - const std::string& mName) { - nl(Out) << "Module* " << fname << "() {"; - nl(Out,1) << "// Module Construction"; - nl(Out) << "Module* mod = new Module(\""; - printEscapedString(mName); - Out << "\", getGlobalContext());"; - if (!TheModule->getTargetTriple().empty()) { - nl(Out) << "mod->setDataLayout(\"" << TheModule->getDataLayoutStr() - << "\");"; - } - if (!TheModule->getTargetTriple().empty()) { - nl(Out) << "mod->setTargetTriple(\"" << TheModule->getTargetTriple() - << "\");"; - } - - if (!TheModule->getModuleInlineAsm().empty()) { - nl(Out) << "mod->setModuleInlineAsm(\""; - printEscapedString(TheModule->getModuleInlineAsm()); - Out << "\");"; - } - nl(Out); - - printModuleBody(); - nl(Out) << "return mod;"; - nl(Out,-1) << "}"; - nl(Out); -} - -void CppWriter::printContents(const std::string& fname, - const std::string& mName) { - Out << "\nModule* " << fname << "(Module *mod) {\n"; - Out << "\nmod->setModuleIdentifier(\""; - printEscapedString(mName); - Out << "\");\n"; - printModuleBody(); - Out << "\nreturn mod;\n"; - Out << "\n}\n"; -} - -void CppWriter::printFunction(const std::string& fname, - const std::string& funcName) { - const Function* F = TheModule->getFunction(funcName); - if (!F) { - error(std::string("Function '") + funcName + "' not found in input module"); - return; - } - Out << "\nFunction* " << fname << "(Module *mod) {\n"; - printFunctionUses(F); - printFunctionHead(F); - printFunctionBody(F); - Out << "return " << getCppName(F) << ";\n"; - Out << "}\n"; -} - -void CppWriter::printFunctions() { - const Module::FunctionListType &funcs = TheModule->getFunctionList(); - Module::const_iterator I = funcs.begin(); - Module::const_iterator IE = funcs.end(); - - for (; I != IE; ++I) { - const Function &func = *I; - if (!func.isDeclaration()) { - std::string name("define_"); - name += func.getName(); - printFunction(name, func.getName()); - } - } -} - -void CppWriter::printVariable(const std::string& fname, - const std::string& varName) { - const GlobalVariable* GV = TheModule->getNamedGlobal(varName); - - if (!GV) { - error(std::string("Variable '") + varName + "' not found in input module"); - return; - } - Out << "\nGlobalVariable* " << fname << "(Module *mod) {\n"; - printVariableUses(GV); - printVariableHead(GV); - printVariableBody(GV); - Out << "return " << getCppName(GV) << ";\n"; - Out << "}\n"; -} - -void CppWriter::printType(const std::string &fname, - const std::string &typeName) { - Type* Ty = TheModule->getTypeByName(typeName); - if (!Ty) { - error(std::string("Type '") + typeName + "' not found in input module"); - return; - } - Out << "\nType* " << fname << "(Module *mod) {\n"; - printType(Ty); - Out << "return " << getCppName(Ty) << ";\n"; - Out << "}\n"; -} - -bool CppWriter::runOnModule(Module &M) { - TheModule = &M; - - // Emit a header - Out << "// Generated by llvm2cpp - DO NOT MODIFY!\n\n"; - - // Get the name of the function we're supposed to generate - std::string fname = FuncName.getValue(); - - // Get the name of the thing we are to generate - std::string tgtname = NameToGenerate.getValue(); - if (GenerationType == GenModule || - GenerationType == GenContents || - GenerationType == GenProgram || - GenerationType == GenFunctions) { - if (tgtname == "!bad!") { - if (M.getModuleIdentifier() == "-") - tgtname = "<stdin>"; - else - tgtname = M.getModuleIdentifier(); - } - } else if (tgtname == "!bad!") - error("You must use the -for option with -gen-{function,variable,type}"); - - switch (WhatToGenerate(GenerationType)) { - case GenProgram: - if (fname.empty()) - fname = "makeLLVMModule"; - printProgram(fname,tgtname); - break; - case GenModule: - if (fname.empty()) - fname = "makeLLVMModule"; - printModule(fname,tgtname); - break; - case GenContents: - if (fname.empty()) - fname = "makeLLVMModuleContents"; - printContents(fname,tgtname); - break; - case GenFunction: - if (fname.empty()) - fname = "makeLLVMFunction"; - printFunction(fname,tgtname); - break; - case GenFunctions: - printFunctions(); - break; - case GenInline: - if (fname.empty()) - fname = "makeLLVMInline"; - printInline(fname,tgtname); - break; - case GenVariable: - if (fname.empty()) - fname = "makeLLVMVariable"; - printVariable(fname,tgtname); - break; - case GenType: - if (fname.empty()) - fname = "makeLLVMType"; - printType(fname,tgtname); - break; - } - - return false; -} - -char CppWriter::ID = 0; - -//===----------------------------------------------------------------------===// -// External Interface declaration -//===----------------------------------------------------------------------===// - -bool CPPTargetMachine::addPassesToEmitFile( - PassManagerBase &PM, raw_pwrite_stream &o, CodeGenFileType FileType, - bool DisableVerify, AnalysisID StartBefore, AnalysisID StartAfter, - AnalysisID StopAfter, MachineFunctionInitializer *MFInitializer) { - if (FileType != TargetMachine::CGFT_AssemblyFile) - return true; - auto FOut = llvm::make_unique<formatted_raw_ostream>(o); - PM.add(new CppWriter(std::move(FOut))); - return false; -} diff --git a/gnu/llvm/lib/Target/CppBackend/CPPTargetMachine.h b/gnu/llvm/lib/Target/CppBackend/CPPTargetMachine.h deleted file mode 100644 index 00e402feffb..00000000000 --- a/gnu/llvm/lib/Target/CppBackend/CPPTargetMachine.h +++ /dev/null @@ -1,44 +0,0 @@ -//===-- CPPTargetMachine.h - TargetMachine for the C++ backend --*- 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 TargetMachine that is used by the C++ backend. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_CPPBACKEND_CPPTARGETMACHINE_H -#define LLVM_LIB_TARGET_CPPBACKEND_CPPTARGETMACHINE_H - -#include "llvm/IR/DataLayout.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetSubtargetInfo.h" - -namespace llvm { - -class formatted_raw_ostream; - -struct CPPTargetMachine : public TargetMachine { - CPPTargetMachine(const Target &T, const Triple &TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, Reloc::Model RM, - CodeModel::Model CM, CodeGenOpt::Level OL) - : TargetMachine(T, "", TT, CPU, FS, Options) {} - -public: - bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out, - CodeGenFileType FileType, bool DisableVerify, - AnalysisID StartBefore, AnalysisID StartAfter, - AnalysisID StopAfter, - MachineFunctionInitializer *MFInitializer) override; -}; - -extern Target TheCppBackendTarget; - -} // End llvm namespace - - -#endif diff --git a/gnu/llvm/lib/Target/CppBackend/LLVMBuild.txt b/gnu/llvm/lib/Target/CppBackend/LLVMBuild.txt deleted file mode 100644 index 122b5e7502f..00000000000 --- a/gnu/llvm/lib/Target/CppBackend/LLVMBuild.txt +++ /dev/null @@ -1,31 +0,0 @@ -;===- ./lib/Target/CppBackend/LLVMBuild.txt --------------------*- Conf -*--===; -; -; The LLVM Compiler Infrastructure -; -; This file is distributed under the University of Illinois Open Source -; License. See LICENSE.TXT for details. -; -;===------------------------------------------------------------------------===; -; -; This is an LLVMBuild description file for the components in this subdirectory. -; -; For more information on the LLVMBuild system, please see: -; -; http://llvm.org/docs/LLVMBuild.html -; -;===------------------------------------------------------------------------===; - -[common] -subdirectories = TargetInfo - -[component_0] -type = TargetGroup -name = CppBackend -parent = Target - -[component_1] -type = Library -name = CppBackendCodeGen -parent = CppBackend -required_libraries = Core CppBackendInfo Support Target -add_to_library_groups = CppBackend diff --git a/gnu/llvm/lib/Target/CppBackend/Makefile b/gnu/llvm/lib/Target/CppBackend/Makefile deleted file mode 100644 index efc7463fda3..00000000000 --- a/gnu/llvm/lib/Target/CppBackend/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/CppBackend/Makefile --- ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMCppBackendCodeGen -DIRS = TargetInfo - -include $(LEVEL)/Makefile.common - -CompileCommonOpts += -Wno-format diff --git a/gnu/llvm/lib/Target/CppBackend/TargetInfo/CMakeLists.txt b/gnu/llvm/lib/Target/CppBackend/TargetInfo/CMakeLists.txt deleted file mode 100644 index d86446f6bc0..00000000000 --- a/gnu/llvm/lib/Target/CppBackend/TargetInfo/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_llvm_library(LLVMCppBackendInfo - CppBackendTargetInfo.cpp - ) diff --git a/gnu/llvm/lib/Target/CppBackend/TargetInfo/CppBackendTargetInfo.cpp b/gnu/llvm/lib/Target/CppBackend/TargetInfo/CppBackendTargetInfo.cpp deleted file mode 100644 index f88d82228ca..00000000000 --- a/gnu/llvm/lib/Target/CppBackend/TargetInfo/CppBackendTargetInfo.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//===-- CppBackendTargetInfo.cpp - CppBackend Target Implementation -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "CPPTargetMachine.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/TargetRegistry.h" -using namespace llvm; - -Target llvm::TheCppBackendTarget; - -static bool CppBackend_TripleMatchQuality(Triple::ArchType Arch) { - // This backend doesn't correspond to any architecture. It must be explicitly - // selected with -march. - return false; -} - -extern "C" void LLVMInitializeCppBackendTargetInfo() { - TargetRegistry::RegisterTarget(TheCppBackendTarget, "cpp", - "C++ backend", - &CppBackend_TripleMatchQuality); -} - -extern "C" void LLVMInitializeCppBackendTargetMC() {} diff --git a/gnu/llvm/lib/Target/CppBackend/TargetInfo/LLVMBuild.txt b/gnu/llvm/lib/Target/CppBackend/TargetInfo/LLVMBuild.txt deleted file mode 100644 index 9c186a52f4f..00000000000 --- a/gnu/llvm/lib/Target/CppBackend/TargetInfo/LLVMBuild.txt +++ /dev/null @@ -1,23 +0,0 @@ -;===- ./lib/Target/CppBackend/TargetInfo/LLVMBuild.txt ---------*- Conf -*--===; -; -; The LLVM Compiler Infrastructure -; -; This file is distributed under the University of Illinois Open Source -; License. See LICENSE.TXT for details. -; -;===------------------------------------------------------------------------===; -; -; This is an LLVMBuild description file for the components in this subdirectory. -; -; For more information on the LLVMBuild system, please see: -; -; http://llvm.org/docs/LLVMBuild.html -; -;===------------------------------------------------------------------------===; - -[component_0] -type = Library -name = CppBackendInfo -parent = CppBackend -required_libraries = Support -add_to_library_groups = CppBackend diff --git a/gnu/llvm/lib/Target/CppBackend/TargetInfo/Makefile b/gnu/llvm/lib/Target/CppBackend/TargetInfo/Makefile deleted file mode 100644 index 6e682838dae..00000000000 --- a/gnu/llvm/lib/Target/CppBackend/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/CppBackend/TargetInfo/Makefile -----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMCppBackendInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Hexagon/AsmParser/Makefile b/gnu/llvm/lib/Target/Hexagon/AsmParser/Makefile deleted file mode 100644 index 0aa0b4140c3..00000000000 --- a/gnu/llvm/lib/Target/Hexagon/AsmParser/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/Hexagon/AsmParser/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMHexagonAsmParser - -# Hack: we need to include 'main' Hexagon target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Hexagon/Disassembler/Makefile b/gnu/llvm/lib/Target/Hexagon/Disassembler/Makefile deleted file mode 100644 index 16c305fe407..00000000000 --- a/gnu/llvm/lib/Target/Hexagon/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===-- lib/Target/Hexagon/Disassembler/Makefile -----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMHexagonDisassembler - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp b/gnu/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp deleted file mode 100644 index 6e2dbc06b12..00000000000 --- a/gnu/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp +++ /dev/null @@ -1,357 +0,0 @@ -//===-- HexagonExpandPredSpillCode.cpp - Expand Predicate Spill Code ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// The Hexagon processor has no instructions that load or store predicate -// registers directly. So, when these registers must be spilled a general -// purpose register must be found and the value copied to/from it from/to -// the predicate register. This code currently does not use the register -// scavenger mechanism available in the allocator. There are two registers -// reserved to allow spilling/restoring predicate registers. One is used to -// hold the predicate value. The other is used when stack frame offsets are -// too large. -// -//===----------------------------------------------------------------------===// - -#include "Hexagon.h" -#include "HexagonMachineFunctionInfo.h" -#include "HexagonSubtarget.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/CodeGen/LatencyPriorityQueue.h" -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineLoopInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/ScheduleHazardRecognizer.h" -#include "llvm/CodeGen/SchedulerRegistry.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" - -using namespace llvm; - - -namespace llvm { - FunctionPass *createHexagonExpandPredSpillCode(); - void initializeHexagonExpandPredSpillCodePass(PassRegistry&); -} - - -namespace { - -class HexagonExpandPredSpillCode : public MachineFunctionPass { - public: - static char ID; - HexagonExpandPredSpillCode() : MachineFunctionPass(ID) { - PassRegistry &Registry = *PassRegistry::getPassRegistry(); - initializeHexagonExpandPredSpillCodePass(Registry); - } - - const char *getPassName() const override { - return "Hexagon Expand Predicate Spill Code"; - } - bool runOnMachineFunction(MachineFunction &Fn) override; -}; - - -char HexagonExpandPredSpillCode::ID = 0; - - -bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { - - const HexagonSubtarget &QST = Fn.getSubtarget<HexagonSubtarget>(); - const HexagonInstrInfo *TII = QST.getInstrInfo(); - - // Loop over all of the basic blocks. - for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); - MBBb != MBBe; ++MBBb) { - MachineBasicBlock *MBB = &*MBBb; - // Traverse the basic block. - for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); - ++MII) { - MachineInstr *MI = MII; - int Opc = MI->getOpcode(); - if (Opc == Hexagon::S2_storerb_pci_pseudo || - Opc == Hexagon::S2_storerh_pci_pseudo || - Opc == Hexagon::S2_storeri_pci_pseudo || - Opc == Hexagon::S2_storerd_pci_pseudo || - Opc == Hexagon::S2_storerf_pci_pseudo) { - unsigned Opcode; - if (Opc == Hexagon::S2_storerd_pci_pseudo) - Opcode = Hexagon::S2_storerd_pci; - else if (Opc == Hexagon::S2_storeri_pci_pseudo) - Opcode = Hexagon::S2_storeri_pci; - else if (Opc == Hexagon::S2_storerh_pci_pseudo) - Opcode = Hexagon::S2_storerh_pci; - else if (Opc == Hexagon::S2_storerf_pci_pseudo) - Opcode = Hexagon::S2_storerf_pci; - else if (Opc == Hexagon::S2_storerb_pci_pseudo) - Opcode = Hexagon::S2_storerb_pci; - else - llvm_unreachable("wrong Opc"); - MachineOperand &Op0 = MI->getOperand(0); - MachineOperand &Op1 = MI->getOperand(1); - MachineOperand &Op2 = MI->getOperand(2); - MachineOperand &Op3 = MI->getOperand(3); // Modifier value. - MachineOperand &Op4 = MI->getOperand(4); - // Emit a "C6 = Rn, C6 is the control register for M0". - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr), - Hexagon::C6)->addOperand(Op3); - // Replace the pseude circ_ldd by the real circ_ldd. - MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Opcode)); - NewMI->addOperand(Op0); - NewMI->addOperand(Op1); - NewMI->addOperand(Op4); - NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0, - false, /*isDef*/ - false, /*isImpl*/ - true /*isKill*/)); - NewMI->addOperand(Op2); - MII = MBB->erase(MI); - --MII; - } else if (Opc == Hexagon::L2_loadrd_pci_pseudo || - Opc == Hexagon::L2_loadri_pci_pseudo || - Opc == Hexagon::L2_loadrh_pci_pseudo || - Opc == Hexagon::L2_loadruh_pci_pseudo|| - Opc == Hexagon::L2_loadrb_pci_pseudo || - Opc == Hexagon::L2_loadrub_pci_pseudo) { - unsigned Opcode; - if (Opc == Hexagon::L2_loadrd_pci_pseudo) - Opcode = Hexagon::L2_loadrd_pci; - else if (Opc == Hexagon::L2_loadri_pci_pseudo) - Opcode = Hexagon::L2_loadri_pci; - else if (Opc == Hexagon::L2_loadrh_pci_pseudo) - Opcode = Hexagon::L2_loadrh_pci; - else if (Opc == Hexagon::L2_loadruh_pci_pseudo) - Opcode = Hexagon::L2_loadruh_pci; - else if (Opc == Hexagon::L2_loadrb_pci_pseudo) - Opcode = Hexagon::L2_loadrb_pci; - else if (Opc == Hexagon::L2_loadrub_pci_pseudo) - Opcode = Hexagon::L2_loadrub_pci; - else - llvm_unreachable("wrong Opc"); - - MachineOperand &Op0 = MI->getOperand(0); - MachineOperand &Op1 = MI->getOperand(1); - MachineOperand &Op2 = MI->getOperand(2); - MachineOperand &Op4 = MI->getOperand(4); // Modifier value. - MachineOperand &Op5 = MI->getOperand(5); - // Emit a "C6 = Rn, C6 is the control register for M0". - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr), - Hexagon::C6)->addOperand(Op4); - // Replace the pseude circ_ldd by the real circ_ldd. - MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Opcode)); - NewMI->addOperand(Op1); - NewMI->addOperand(Op0); - NewMI->addOperand(Op2); - NewMI->addOperand(Op5); - NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0, - false, /*isDef*/ - false, /*isImpl*/ - true /*isKill*/)); - MII = MBB->erase(MI); - --MII; - } else if (Opc == Hexagon::L2_loadrd_pbr_pseudo || - Opc == Hexagon::L2_loadri_pbr_pseudo || - Opc == Hexagon::L2_loadrh_pbr_pseudo || - Opc == Hexagon::L2_loadruh_pbr_pseudo|| - Opc == Hexagon::L2_loadrb_pbr_pseudo || - Opc == Hexagon::L2_loadrub_pbr_pseudo) { - unsigned Opcode; - if (Opc == Hexagon::L2_loadrd_pbr_pseudo) - Opcode = Hexagon::L2_loadrd_pbr; - else if (Opc == Hexagon::L2_loadri_pbr_pseudo) - Opcode = Hexagon::L2_loadri_pbr; - else if (Opc == Hexagon::L2_loadrh_pbr_pseudo) - Opcode = Hexagon::L2_loadrh_pbr; - else if (Opc == Hexagon::L2_loadruh_pbr_pseudo) - Opcode = Hexagon::L2_loadruh_pbr; - else if (Opc == Hexagon::L2_loadrb_pbr_pseudo) - Opcode = Hexagon::L2_loadrb_pbr; - else if (Opc == Hexagon::L2_loadrub_pbr_pseudo) - Opcode = Hexagon::L2_loadrub_pbr; - else - llvm_unreachable("wrong Opc"); - MachineOperand &Op0 = MI->getOperand(0); - MachineOperand &Op1 = MI->getOperand(1); - MachineOperand &Op2 = MI->getOperand(2); - MachineOperand &Op4 = MI->getOperand(4); // Modifier value. - // Emit a "C6 = Rn, C6 is the control register for M0". - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr), - Hexagon::C6)->addOperand(Op4); - // Replace the pseudo brev_ldd by the real brev_ldd. - MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Opcode)); - NewMI->addOperand(Op1); - NewMI->addOperand(Op0); - NewMI->addOperand(Op2); - NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0, - false, /*isDef*/ - false, /*isImpl*/ - true /*isKill*/)); - MII = MBB->erase(MI); - --MII; - } else if (Opc == Hexagon::S2_storerd_pbr_pseudo || - Opc == Hexagon::S2_storeri_pbr_pseudo || - Opc == Hexagon::S2_storerh_pbr_pseudo || - Opc == Hexagon::S2_storerb_pbr_pseudo || - Opc == Hexagon::S2_storerf_pbr_pseudo) { - unsigned Opcode; - if (Opc == Hexagon::S2_storerd_pbr_pseudo) - Opcode = Hexagon::S2_storerd_pbr; - else if (Opc == Hexagon::S2_storeri_pbr_pseudo) - Opcode = Hexagon::S2_storeri_pbr; - else if (Opc == Hexagon::S2_storerh_pbr_pseudo) - Opcode = Hexagon::S2_storerh_pbr; - else if (Opc == Hexagon::S2_storerf_pbr_pseudo) - Opcode = Hexagon::S2_storerf_pbr; - else if (Opc == Hexagon::S2_storerb_pbr_pseudo) - Opcode = Hexagon::S2_storerb_pbr; - else - llvm_unreachable("wrong Opc"); - MachineOperand &Op0 = MI->getOperand(0); - MachineOperand &Op1 = MI->getOperand(1); - MachineOperand &Op2 = MI->getOperand(2); - MachineOperand &Op3 = MI->getOperand(3); // Modifier value. - // Emit a "C6 = Rn, C6 is the control register for M0". - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr), - Hexagon::C6)->addOperand(Op3); - // Replace the pseudo brev_ldd by the real brev_ldd. - MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Opcode)); - NewMI->addOperand(Op0); - NewMI->addOperand(Op1); - NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0, - false, /*isDef*/ - false, /*isImpl*/ - true /*isKill*/)); - NewMI->addOperand(Op2); - MII = MBB->erase(MI); - --MII; - } else if (Opc == Hexagon::STriw_pred) { - // STriw_pred [R30], ofst, SrcReg; - unsigned FP = MI->getOperand(0).getReg(); - assert(FP == QST.getRegisterInfo()->getFrameRegister() && - "Not a Frame Pointer, Nor a Spill Slot"); - assert(MI->getOperand(1).isImm() && "Not an offset"); - int Offset = MI->getOperand(1).getImm(); - int SrcReg = MI->getOperand(2).getReg(); - assert(Hexagon::PredRegsRegClass.contains(SrcReg) && - "Not a predicate register"); - if (!TII->isValidOffset(Hexagon::S2_storeri_io, Offset)) { - if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) { - BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::CONST32_Int_Real), - HEXAGON_RESERVED_REG_1).addImm(Offset); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add), - HEXAGON_RESERVED_REG_1) - .addReg(FP).addReg(HEXAGON_RESERVED_REG_1); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), - HEXAGON_RESERVED_REG_2).addReg(SrcReg); - BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::S2_storeri_io)) - .addReg(HEXAGON_RESERVED_REG_1) - .addImm(0).addReg(HEXAGON_RESERVED_REG_2); - } else { - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi), - HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), - HEXAGON_RESERVED_REG_2).addReg(SrcReg); - BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::S2_storeri_io)) - .addReg(HEXAGON_RESERVED_REG_1) - .addImm(0) - .addReg(HEXAGON_RESERVED_REG_2); - } - } else { - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), - HEXAGON_RESERVED_REG_2).addReg(SrcReg); - BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::S2_storeri_io)). - addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2); - } - MII = MBB->erase(MI); - --MII; - } else if (Opc == Hexagon::LDriw_pred) { - // DstReg = LDriw_pred [R30], ofst. - int DstReg = MI->getOperand(0).getReg(); - assert(Hexagon::PredRegsRegClass.contains(DstReg) && - "Not a predicate register"); - unsigned FP = MI->getOperand(1).getReg(); - assert(FP == QST.getRegisterInfo()->getFrameRegister() && - "Not a Frame Pointer, Nor a Spill Slot"); - assert(MI->getOperand(2).isImm() && "Not an offset"); - int Offset = MI->getOperand(2).getImm(); - if (!TII->isValidOffset(Hexagon::L2_loadri_io, Offset)) { - if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) { - BuildMI(*MBB, MII, MI->getDebugLoc(), - TII->get(Hexagon::CONST32_Int_Real), - HEXAGON_RESERVED_REG_1).addImm(Offset); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add), - HEXAGON_RESERVED_REG_1) - .addReg(FP) - .addReg(HEXAGON_RESERVED_REG_1); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), - HEXAGON_RESERVED_REG_2) - .addReg(HEXAGON_RESERVED_REG_1) - .addImm(0); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), - DstReg).addReg(HEXAGON_RESERVED_REG_2); - } else { - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi), - HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), - HEXAGON_RESERVED_REG_2) - .addReg(HEXAGON_RESERVED_REG_1) - .addImm(0); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), - DstReg).addReg(HEXAGON_RESERVED_REG_2); - } - } else { - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), - HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset); - BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), - DstReg).addReg(HEXAGON_RESERVED_REG_2); - } - MII = MBB->erase(MI); - --MII; - } - } - } - - return true; -} - -} - -//===----------------------------------------------------------------------===// -// Public Constructor Functions -//===----------------------------------------------------------------------===// - -static void initializePassOnce(PassRegistry &Registry) { - const char *Name = "Hexagon Expand Predicate Spill Code"; - PassInfo *PI = new PassInfo(Name, "hexagon-spill-pred", - &HexagonExpandPredSpillCode::ID, - nullptr, false, false); - Registry.registerPass(*PI, true); -} - -void llvm::initializeHexagonExpandPredSpillCodePass(PassRegistry &Registry) { - CALL_ONCE_INITIALIZATION(initializePassOnce) -} - -FunctionPass* -llvm::createHexagonExpandPredSpillCode() { - return new HexagonExpandPredSpillCode(); -} diff --git a/gnu/llvm/lib/Target/Hexagon/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/Hexagon/MCTargetDesc/Makefile deleted file mode 100644 index 885be2ddbd8..00000000000 --- a/gnu/llvm/lib/Target/Hexagon/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Hexagon/TargetDesc/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMHexagonDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Hexagon/Makefile b/gnu/llvm/lib/Target/Hexagon/Makefile deleted file mode 100644 index c53b8e56aaf..00000000000 --- a/gnu/llvm/lib/Target/Hexagon/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -##===- lib/Target/Hexagon/Makefile -------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../.. -LIBRARYNAME = LLVMHexagonCodeGen -TARGET = Hexagon - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = HexagonGenRegisterInfo.inc \ - HexagonGenInstrInfo.inc \ - HexagonGenAsmMatcher.inc \ - HexagonGenAsmWriter.inc \ - HexagonGenDAGISel.inc HexagonGenSubtargetInfo.inc \ - HexagonGenCallingConv.inc \ - HexagonGenDFAPacketizer.inc \ - HexagonGenMCCodeEmitter.inc \ - HexagonGenDisassemblerTables.inc - -DIRS = TargetInfo MCTargetDesc Disassembler AsmParser - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Hexagon/TargetInfo/Makefile b/gnu/llvm/lib/Target/Hexagon/TargetInfo/Makefile deleted file mode 100644 index 494cca11224..00000000000 --- a/gnu/llvm/lib/Target/Hexagon/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/Hexagon/TargetInfo/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMHexagonInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/MSP430/InstPrinter/Makefile b/gnu/llvm/lib/Target/MSP430/InstPrinter/Makefile deleted file mode 100644 index a5293ab8a23..00000000000 --- a/gnu/llvm/lib/Target/MSP430/InstPrinter/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/MSP430/AsmPrinter/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMMSP430AsmPrinter - -# Hack: we need to include 'main' MSP430 target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/MSP430/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/MSP430/MCTargetDesc/Makefile deleted file mode 100644 index bb857998eef..00000000000 --- a/gnu/llvm/lib/Target/MSP430/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/MSP430/TargetDesc/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMMSP430Desc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/MSP430/Makefile b/gnu/llvm/lib/Target/MSP430/Makefile deleted file mode 100644 index 82216edd81e..00000000000 --- a/gnu/llvm/lib/Target/MSP430/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -##===- lib/Target/MSP430/Makefile --------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMMSP430CodeGen -TARGET = MSP430 - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = MSP430GenRegisterInfo.inc MSP430GenInstrInfo.inc \ - MSP430GenAsmWriter.inc \ - MSP430GenDAGISel.inc MSP430GenCallingConv.inc \ - MSP430GenSubtargetInfo.inc - -DIRS = InstPrinter TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Target/MSP430/TargetInfo/Makefile b/gnu/llvm/lib/Target/MSP430/TargetInfo/Makefile deleted file mode 100644 index abb08f2548e..00000000000 --- a/gnu/llvm/lib/Target/MSP430/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/MSP430/TargetInfo/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMMSP430Info - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Makefile b/gnu/llvm/lib/Target/Makefile deleted file mode 100644 index 50a360f1f86..00000000000 --- a/gnu/llvm/lib/Target/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -#===- lib/Target/Makefile ----------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMTarget -BUILD_ARCHIVE = 1 - -# We include this early so we can access the value of TARGETS_TO_BUILD as the -# value for PARALLEL_DIRS which must be set before Makefile.rules is included -include $(LEVEL)/Makefile.config - -PARALLEL_DIRS := $(TARGETS_TO_BUILD) - -include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/gnu/llvm/lib/Target/Mips/AsmParser/Makefile b/gnu/llvm/lib/Target/Mips/AsmParser/Makefile deleted file mode 100644 index 679acee9fe7..00000000000 --- a/gnu/llvm/lib/Target/Mips/AsmParser/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/Mips/AsmParser/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsAsmParser - -# Hack: we need to include 'main' mips target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Mips/Disassembler/Makefile b/gnu/llvm/lib/Target/Mips/Disassembler/Makefile deleted file mode 100644 index 7900373dd2b..00000000000 --- a/gnu/llvm/lib/Target/Mips/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Mips/Disassembler/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsDisassembler - -# Hack: we need to include 'main' Mips target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Mips/InstPrinter/Makefile b/gnu/llvm/lib/Target/Mips/InstPrinter/Makefile deleted file mode 100644 index f07f3ed381e..00000000000 --- a/gnu/llvm/lib/Target/Mips/InstPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Mips/AsmPrinter/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsAsmPrinter - -# Hack: we need to include 'main' mips target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Mips/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/Mips/MCTargetDesc/Makefile deleted file mode 100644 index 22a27218f28..00000000000 --- a/gnu/llvm/lib/Target/Mips/MCTargetDesc/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -##===- lib/Target/Mips/TargetDesc/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Target/Mips/Makefile b/gnu/llvm/lib/Target/Mips/Makefile deleted file mode 100644 index 56db450f696..00000000000 --- a/gnu/llvm/lib/Target/Mips/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -##===- lib/Target/Mips/Makefile ----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMMipsCodeGen -TARGET = Mips - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \ - MipsGenAsmWriter.inc MipsGenFastISel.inc \ - MipsGenDAGISel.inc MipsGenCallingConv.inc \ - MipsGenSubtargetInfo.inc MipsGenMCCodeEmitter.inc \ - MipsGenDisassemblerTables.inc \ - MipsGenMCPseudoLowering.inc MipsGenAsmMatcher.inc - -DIRS = InstPrinter Disassembler AsmParser TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Target/Mips/TargetInfo/Makefile b/gnu/llvm/lib/Target/Mips/TargetInfo/Makefile deleted file mode 100644 index 32f4e1695b1..00000000000 --- a/gnu/llvm/lib/Target/Mips/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/Mips/TargetInfo/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/NVPTX/InstPrinter/Makefile b/gnu/llvm/lib/Target/NVPTX/InstPrinter/Makefile deleted file mode 100644 index 7b7865436bf..00000000000 --- a/gnu/llvm/lib/Target/NVPTX/InstPrinter/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/NVPTX/AsmPrinter/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMNVPTXAsmPrinter - -# Hack: we need to include 'main' ptx target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/NVPTX/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/NVPTX/MCTargetDesc/Makefile deleted file mode 100644 index 31d06cb5948..00000000000 --- a/gnu/llvm/lib/Target/NVPTX/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/NVPTX/TargetDesc/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMNVPTXDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/NVPTX/Makefile b/gnu/llvm/lib/Target/NVPTX/Makefile deleted file mode 100644 index 8db20ebed2c..00000000000 --- a/gnu/llvm/lib/Target/NVPTX/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -##===- lib/Target/NVPTX/Makefile ---------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMNVPTXCodeGen -TARGET = NVPTX - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = NVPTXGenAsmWriter.inc \ - NVPTXGenDAGISel.inc \ - NVPTXGenInstrInfo.inc \ - NVPTXGenRegisterInfo.inc \ - NVPTXGenSubtargetInfo.inc - -DIRS = InstPrinter TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/NVPTX/TargetInfo/Makefile b/gnu/llvm/lib/Target/NVPTX/TargetInfo/Makefile deleted file mode 100644 index 8622315b47b..00000000000 --- a/gnu/llvm/lib/Target/NVPTX/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/NVPTX/TargetInfo/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMNVPTXInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/PowerPC/AsmParser/Makefile b/gnu/llvm/lib/Target/PowerPC/AsmParser/Makefile deleted file mode 100644 index c8a8915685e..00000000000 --- a/gnu/llvm/lib/Target/PowerPC/AsmParser/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/PowerPC/AsmParser/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMPowerPCAsmParser - -# Hack: we need to include 'main' PowerPC target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/PowerPC/Disassembler/Makefile b/gnu/llvm/lib/Target/PowerPC/Disassembler/Makefile deleted file mode 100644 index 86e3b475220..00000000000 --- a/gnu/llvm/lib/Target/PowerPC/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===-- lib/Target/PowerPC/Disassembler/Makefile -----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMPowerPCDisassembler - -# Hack: we need to include 'main' PPC target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/PowerPC/InstPrinter/Makefile b/gnu/llvm/lib/Target/PowerPC/InstPrinter/Makefile deleted file mode 100644 index f097e84248f..00000000000 --- a/gnu/llvm/lib/Target/PowerPC/InstPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/PowerPC/AsmPrinter/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMPowerPCAsmPrinter - -# Hack: we need to include 'main' powerpc target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/PowerPC/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/PowerPC/MCTargetDesc/Makefile deleted file mode 100644 index 9db66622cce..00000000000 --- a/gnu/llvm/lib/Target/PowerPC/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/PowerPC/TargetDesc/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMPowerPCDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/PowerPC/Makefile b/gnu/llvm/lib/Target/PowerPC/Makefile deleted file mode 100644 index cf516f4e5ec..00000000000 --- a/gnu/llvm/lib/Target/PowerPC/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -##===- lib/Target/PowerPC/Makefile -------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMPowerPCCodeGen -TARGET = PPC - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = PPCGenRegisterInfo.inc PPCGenAsmMatcher.inc \ - PPCGenAsmWriter.inc \ - PPCGenInstrInfo.inc PPCGenDAGISel.inc \ - PPCGenSubtargetInfo.inc PPCGenCallingConv.inc \ - PPCGenMCCodeEmitter.inc PPCGenFastISel.inc \ - PPCGenDisassemblerTables.inc - -DIRS = AsmParser Disassembler InstPrinter TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/PowerPC/PPCLoopDataPrefetch.cpp b/gnu/llvm/lib/Target/PowerPC/PPCLoopDataPrefetch.cpp deleted file mode 100644 index e3a35d5df35..00000000000 --- a/gnu/llvm/lib/Target/PowerPC/PPCLoopDataPrefetch.cpp +++ /dev/null @@ -1,233 +0,0 @@ -//===-------- PPCLoopDataPrefetch.cpp - Loop Data Prefetching Pass --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a Loop Data Prefetching Pass. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "ppc-loop-data-prefetch" -#include "PPC.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/ADT/DepthFirstIterator.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/AssumptionCache.h" -#include "llvm/Analysis/CodeMetrics.h" -#include "llvm/Analysis/InstructionSimplify.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/ScalarEvolution.h" -#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" -#include "llvm/Analysis/ScalarEvolutionExpander.h" -#include "llvm/Analysis/ScalarEvolutionExpressions.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Local.h" -#include "llvm/Transforms/Utils/ValueMapper.h" -using namespace llvm; - -// By default, we limit this to creating 16 PHIs (which is a little over half -// of the allocatable register set). -static cl::opt<bool> -PrefetchWrites("ppc-loop-prefetch-writes", cl::Hidden, cl::init(false), - cl::desc("Prefetch write addresses")); - -// This seems like a reasonable default for the BG/Q (this pass is enabled, by -// default, only on the BG/Q). -static cl::opt<unsigned> -PrefDist("ppc-loop-prefetch-distance", cl::Hidden, cl::init(300), - cl::desc("The loop prefetch distance")); - -static cl::opt<unsigned> -CacheLineSize("ppc-loop-prefetch-cache-line", cl::Hidden, cl::init(64), - cl::desc("The loop prefetch cache line size")); - -namespace llvm { - void initializePPCLoopDataPrefetchPass(PassRegistry&); -} - -namespace { - - class PPCLoopDataPrefetch : public FunctionPass { - public: - static char ID; // Pass ID, replacement for typeid - PPCLoopDataPrefetch() : FunctionPass(ID) { - initializePPCLoopDataPrefetchPass(*PassRegistry::getPassRegistry()); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<AssumptionCacheTracker>(); - AU.addPreserved<DominatorTreeWrapperPass>(); - AU.addRequired<LoopInfoWrapperPass>(); - AU.addPreserved<LoopInfoWrapperPass>(); - AU.addRequired<ScalarEvolutionWrapperPass>(); - // FIXME: For some reason, preserving SE here breaks LSR (even if - // this pass changes nothing). - // AU.addPreserved<ScalarEvolutionWrapperPass>(); - AU.addRequired<TargetTransformInfoWrapperPass>(); - } - - bool runOnFunction(Function &F) override; - bool runOnLoop(Loop *L); - - private: - AssumptionCache *AC; - LoopInfo *LI; - ScalarEvolution *SE; - const TargetTransformInfo *TTI; - const DataLayout *DL; - }; -} - -char PPCLoopDataPrefetch::ID = 0; -INITIALIZE_PASS_BEGIN(PPCLoopDataPrefetch, "ppc-loop-data-prefetch", - "PPC Loop Data Prefetch", false, false) -INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) -INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) -INITIALIZE_PASS_END(PPCLoopDataPrefetch, "ppc-loop-data-prefetch", - "PPC Loop Data Prefetch", false, false) - -FunctionPass *llvm::createPPCLoopDataPrefetchPass() { return new PPCLoopDataPrefetch(); } - -bool PPCLoopDataPrefetch::runOnFunction(Function &F) { - LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); - SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); - DL = &F.getParent()->getDataLayout(); - AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); - TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); - - bool MadeChange = false; - - for (auto I = LI->begin(), IE = LI->end(); I != IE; ++I) - for (auto L = df_begin(*I), LE = df_end(*I); L != LE; ++L) - MadeChange |= runOnLoop(*L); - - return MadeChange; -} - -bool PPCLoopDataPrefetch::runOnLoop(Loop *L) { - bool MadeChange = false; - - // Only prefetch in the inner-most loop - if (!L->empty()) - return MadeChange; - - SmallPtrSet<const Value *, 32> EphValues; - CodeMetrics::collectEphemeralValues(L, AC, EphValues); - - // Calculate the number of iterations ahead to prefetch - CodeMetrics Metrics; - for (Loop::block_iterator I = L->block_begin(), IE = L->block_end(); - I != IE; ++I) { - - // If the loop already has prefetches, then assume that the user knows - // what he or she is doing and don't add any more. - for (BasicBlock::iterator J = (*I)->begin(), JE = (*I)->end(); - J != JE; ++J) - if (CallInst *CI = dyn_cast<CallInst>(J)) - if (Function *F = CI->getCalledFunction()) - if (F->getIntrinsicID() == Intrinsic::prefetch) - return MadeChange; - - Metrics.analyzeBasicBlock(*I, *TTI, EphValues); - } - unsigned LoopSize = Metrics.NumInsts; - if (!LoopSize) - LoopSize = 1; - - unsigned ItersAhead = PrefDist/LoopSize; - if (!ItersAhead) - ItersAhead = 1; - - SmallVector<std::pair<Instruction *, const SCEVAddRecExpr *>, 16> PrefLoads; - for (Loop::block_iterator I = L->block_begin(), IE = L->block_end(); - I != IE; ++I) { - for (BasicBlock::iterator J = (*I)->begin(), JE = (*I)->end(); - J != JE; ++J) { - Value *PtrValue; - Instruction *MemI; - - if (LoadInst *LMemI = dyn_cast<LoadInst>(J)) { - MemI = LMemI; - PtrValue = LMemI->getPointerOperand(); - } else if (StoreInst *SMemI = dyn_cast<StoreInst>(J)) { - if (!PrefetchWrites) continue; - MemI = SMemI; - PtrValue = SMemI->getPointerOperand(); - } else continue; - - unsigned PtrAddrSpace = PtrValue->getType()->getPointerAddressSpace(); - if (PtrAddrSpace) - continue; - - if (L->isLoopInvariant(PtrValue)) - continue; - - const SCEV *LSCEV = SE->getSCEV(PtrValue); - const SCEVAddRecExpr *LSCEVAddRec = dyn_cast<SCEVAddRecExpr>(LSCEV); - if (!LSCEVAddRec) - continue; - - // We don't want to double prefetch individual cache lines. If this load - // is known to be within one cache line of some other load that has - // already been prefetched, then don't prefetch this one as well. - bool DupPref = false; - for (SmallVector<std::pair<Instruction *, const SCEVAddRecExpr *>, - 16>::iterator K = PrefLoads.begin(), KE = PrefLoads.end(); - K != KE; ++K) { - const SCEV *PtrDiff = SE->getMinusSCEV(LSCEVAddRec, K->second); - if (const SCEVConstant *ConstPtrDiff = - dyn_cast<SCEVConstant>(PtrDiff)) { - int64_t PD = std::abs(ConstPtrDiff->getValue()->getSExtValue()); - if (PD < (int64_t) CacheLineSize) { - DupPref = true; - break; - } - } - } - if (DupPref) - continue; - - const SCEV *NextLSCEV = SE->getAddExpr(LSCEVAddRec, SE->getMulExpr( - SE->getConstant(LSCEVAddRec->getType(), ItersAhead), - LSCEVAddRec->getStepRecurrence(*SE))); - if (!isSafeToExpand(NextLSCEV, *SE)) - continue; - - PrefLoads.push_back(std::make_pair(MemI, LSCEVAddRec)); - - Type *I8Ptr = Type::getInt8PtrTy((*I)->getContext(), PtrAddrSpace); - SCEVExpander SCEVE(*SE, J->getModule()->getDataLayout(), "prefaddr"); - Value *PrefPtrValue = SCEVE.expandCodeFor(NextLSCEV, I8Ptr, MemI); - - IRBuilder<> Builder(MemI); - Module *M = (*I)->getParent()->getParent(); - Type *I32 = Type::getInt32Ty((*I)->getContext()); - Value *PrefetchFunc = Intrinsic::getDeclaration(M, Intrinsic::prefetch); - Builder.CreateCall( - PrefetchFunc, - {PrefPtrValue, - ConstantInt::get(I32, MemI->mayReadFromMemory() ? 0 : 1), - ConstantInt::get(I32, 3), ConstantInt::get(I32, 1)}); - - MadeChange = true; - } - } - - return MadeChange; -} - diff --git a/gnu/llvm/lib/Target/PowerPC/TargetInfo/Makefile b/gnu/llvm/lib/Target/PowerPC/TargetInfo/Makefile deleted file mode 100644 index 2d0560d275f..00000000000 --- a/gnu/llvm/lib/Target/PowerPC/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/PowerPC/TargetInfo/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMPowerPCInfo - -# Hack: we need to include 'main' target directory to grab private headers -override CPPFLAGS += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Sparc/AsmParser/Makefile b/gnu/llvm/lib/Target/Sparc/AsmParser/Makefile deleted file mode 100644 index 46b3e45f2be..00000000000 --- a/gnu/llvm/lib/Target/Sparc/AsmParser/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/Sparc/AsmParser/Makefile ------------------*- Makefile-*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMSparcAsmParser - -# Hack: we need to include 'main' Sparc target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Sparc/Disassembler/Makefile b/gnu/llvm/lib/Target/Sparc/Disassembler/Makefile deleted file mode 100644 index bc17ddc48c7..00000000000 --- a/gnu/llvm/lib/Target/Sparc/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Sparc/Disassembler/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMSparcDisassembler - -# Hack: we need to include 'main' Sparc target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Sparc/InstPrinter/Makefile b/gnu/llvm/lib/Target/Sparc/InstPrinter/Makefile deleted file mode 100644 index 2dabd82965f..00000000000 --- a/gnu/llvm/lib/Target/Sparc/InstPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Sparc/InstPrinter/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMSparcAsmPrinter - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Sparc/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/Sparc/MCTargetDesc/Makefile deleted file mode 100644 index abcbe2da18e..00000000000 --- a/gnu/llvm/lib/Target/Sparc/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Sparc/TargetDesc/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMSparcDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/Sparc/Makefile b/gnu/llvm/lib/Target/Sparc/Makefile deleted file mode 100644 index c2a95b47151..00000000000 --- a/gnu/llvm/lib/Target/Sparc/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -##===- lib/Target/Sparc/Makefile ---------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMSparcCodeGen -TARGET = Sparc - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \ - SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \ - SparcGenDAGISel.inc SparcGenDisassemblerTables.inc \ - SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \ - SparcGenMCCodeEmitter.inc - -DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Target/Sparc/TargetInfo/Makefile b/gnu/llvm/lib/Target/Sparc/TargetInfo/Makefile deleted file mode 100644 index 641ed87160c..00000000000 --- a/gnu/llvm/lib/Target/Sparc/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/Sparc/TargetInfo/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMSparcInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/SystemZ/AsmParser/Makefile b/gnu/llvm/lib/Target/SystemZ/AsmParser/Makefile deleted file mode 100644 index 623ae2c4e3e..00000000000 --- a/gnu/llvm/lib/Target/SystemZ/AsmParser/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/SystemZ/AsmParser/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMSystemZAsmParser - -# Hack: we need to include 'main' SystemZ target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/SystemZ/Disassembler/Makefile b/gnu/llvm/lib/Target/SystemZ/Disassembler/Makefile deleted file mode 100644 index efc4cc8e9cb..00000000000 --- a/gnu/llvm/lib/Target/SystemZ/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===-- lib/Target/SystemZ/Disassembler/Makefile -----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMSystemZDisassembler - -# Hack: we need to include 'main' x86 target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/SystemZ/InstPrinter/Makefile b/gnu/llvm/lib/Target/SystemZ/InstPrinter/Makefile deleted file mode 100644 index 3ba8126735a..00000000000 --- a/gnu/llvm/lib/Target/SystemZ/InstPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/SystemZ/AsmPrinter/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMSystemZAsmPrinter - -# Hack: we need to include 'main' mips target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/SystemZ/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/SystemZ/MCTargetDesc/Makefile deleted file mode 100644 index 08f1a9d51fb..00000000000 --- a/gnu/llvm/lib/Target/SystemZ/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/SystemZ/TargetDesc/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMSystemZDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/SystemZ/Makefile b/gnu/llvm/lib/Target/SystemZ/Makefile deleted file mode 100644 index 732c3172553..00000000000 --- a/gnu/llvm/lib/Target/SystemZ/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -##===- lib/Target/SystemZ/Makefile -------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMSystemZCodeGen -TARGET = SystemZ - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = SystemZGenRegisterInfo.inc \ - SystemZGenAsmWriter.inc \ - SystemZGenAsmMatcher.inc \ - SystemZGenDisassemblerTables.inc \ - SystemZGenInstrInfo.inc \ - SystemZGenDAGISel.inc \ - SystemZGenSubtargetInfo.inc \ - SystemZGenCallingConv.inc \ - SystemZGenMCCodeEmitter.inc - -DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Target/SystemZ/TargetInfo/Makefile b/gnu/llvm/lib/Target/SystemZ/TargetInfo/Makefile deleted file mode 100644 index 0be80eb4e6a..00000000000 --- a/gnu/llvm/lib/Target/SystemZ/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/SystemZ/TargetInfo/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMSystemZInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/WebAssembly/Disassembler/Makefile b/gnu/llvm/lib/Target/WebAssembly/Disassembler/Makefile deleted file mode 100644 index bcd36ba6f01..00000000000 --- a/gnu/llvm/lib/Target/WebAssembly/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===-- lib/Target/WebAssembly/Disassembler/Makefile -------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMWebAssemblyDisassembler - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/WebAssembly/InstPrinter/Makefile b/gnu/llvm/lib/Target/WebAssembly/InstPrinter/Makefile deleted file mode 100644 index 87534379f79..00000000000 --- a/gnu/llvm/lib/Target/WebAssembly/InstPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/WebAssembly/AsmPrinter/Makefile ----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMWebAssemblyAsmPrinter - -# Hack: we need to include 'main' wasm target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/WebAssembly/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/WebAssembly/MCTargetDesc/Makefile deleted file mode 100644 index 11dcb4ff607..00000000000 --- a/gnu/llvm/lib/Target/WebAssembly/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/WebAssembly/TargetDesc/Makefile ----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMWebAssemblyDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/WebAssembly/Makefile b/gnu/llvm/lib/Target/WebAssembly/Makefile deleted file mode 100644 index c501a2b1ab1..00000000000 --- a/gnu/llvm/lib/Target/WebAssembly/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -##===- lib/Target/WebAssembly/Makefile ---------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMWebAssemblyCodeGen -TARGET = WebAssembly - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = \ - WebAssemblyGenAsmWriter.inc \ - WebAssemblyGenDAGISel.inc \ - WebAssemblyGenFastISel.inc \ - WebAssemblyGenInstrInfo.inc \ - WebAssemblyGenMCCodeEmitter.inc \ - WebAssemblyGenRegisterInfo.inc \ - WebAssemblyGenSubtargetInfo.inc - -DIRS = InstPrinter TargetInfo MCTargetDesc Disassembler - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/WebAssembly/Relooper.cpp b/gnu/llvm/lib/Target/WebAssembly/Relooper.cpp deleted file mode 100644 index 9b718ef094a..00000000000 --- a/gnu/llvm/lib/Target/WebAssembly/Relooper.cpp +++ /dev/null @@ -1,984 +0,0 @@ -//===-- Relooper.cpp - Top-level interface for WebAssembly ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===---------------------------------------------------------------------===// -/// -/// \file -/// \brief This implements the Relooper algorithm. This implementation includes -/// optimizations added since the original academic paper [1] was published. -/// -/// [1] Alon Zakai. 2011. Emscripten: an LLVM-to-JavaScript compiler. In -/// Proceedings of the ACM international conference companion on Object -/// oriented programming systems languages and applications companion -/// (SPLASH '11). ACM, New York, NY, USA, 301-312. DOI=10.1145/2048147.2048224 -/// http://doi.acm.org/10.1145/2048147.2048224 -/// -//===-------------------------------------------------------------------===// - -#include "Relooper.h" -#include "WebAssembly.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/Function.h" -#include "llvm/Pass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -#include <cstring> -#include <cstdlib> -#include <functional> -#include <list> -#include <stack> -#include <string> - -#define DEBUG_TYPE "relooper" - -using namespace llvm; -using namespace Relooper; - -static cl::opt<int> RelooperSplittingFactor( - "relooper-splitting-factor", - cl::desc( - "How much to discount code size when deciding whether to split a node"), - cl::init(5)); - -static cl::opt<unsigned> RelooperMultipleSwitchThreshold( - "relooper-multiple-switch-threshold", - cl::desc( - "How many entries to allow in a multiple before we use a switch"), - cl::init(10)); - -static cl::opt<unsigned> RelooperNestingLimit( - "relooper-nesting-limit", - cl::desc( - "How much nesting is acceptable"), - cl::init(20)); - - -namespace { -/// -/// Implements the relooper algorithm for a function's blocks. -/// -/// Implementation details: The Relooper instance has -/// ownership of the blocks and shapes, and frees them when done. -/// -struct RelooperAlgorithm { - std::deque<Block *> Blocks; - std::deque<Shape *> Shapes; - Shape *Root; - bool MinSize; - int BlockIdCounter; - int ShapeIdCounter; - - RelooperAlgorithm(); - ~RelooperAlgorithm(); - - void AddBlock(Block *New, int Id = -1); - - // Calculates the shapes - void Calculate(Block *Entry); - - // Sets us to try to minimize size - void SetMinSize(bool MinSize_) { MinSize = MinSize_; } -}; - -struct RelooperAnalysis final : public FunctionPass { - static char ID; - RelooperAnalysis() : FunctionPass(ID) {} - const char *getPassName() const override { return "relooper"; } - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - bool runOnFunction(Function &F) override; -}; -} - -// RelooperAnalysis - -char RelooperAnalysis::ID = 0; -FunctionPass *llvm::createWebAssemblyRelooper() { - return new RelooperAnalysis(); -} - -bool RelooperAnalysis::runOnFunction(Function &F) { - DEBUG(dbgs() << "Relooping function '" << F.getName() << "'\n"); - RelooperAlgorithm R; - // FIXME: remove duplication between relooper's and LLVM's BBs. - std::map<const BasicBlock *, Block *> BB2B; - std::map<const Block *, const BasicBlock *> B2BB; - for (const BasicBlock &BB : F) { - // FIXME: getName is wrong here, Code is meant to represent amount of code. - // FIXME: use BranchVarInit for switch. - Block *B = new Block(BB.getName().str().data(), /*BranchVarInit=*/nullptr); - R.AddBlock(B); - assert(BB2B.find(&BB) == BB2B.end() && "Inserting the same block twice"); - assert(B2BB.find(B) == B2BB.end() && "Inserting the same block twice"); - BB2B[&BB] = B; - B2BB[B] = &BB; - } - for (Block *B : R.Blocks) { - const BasicBlock *BB = B2BB[B]; - for (const BasicBlock *Successor : successors(BB)) - // FIXME: add branch's Condition and Code below. - B->AddBranchTo(BB2B[Successor], /*Condition=*/nullptr, /*Code=*/nullptr); - } - R.Calculate(BB2B[&F.getEntryBlock()]); - return false; // Analysis passes don't modify anything. -} - -// Helpers - -typedef MapVector<Block *, BlockSet> BlockBlockSetMap; -typedef std::list<Block *> BlockList; - -template <class T, class U> -static bool contains(const T &container, const U &contained) { - return container.count(contained); -} - - -// Branch - -Branch::Branch(const char *ConditionInit, const char *CodeInit) - : Ancestor(nullptr), Labeled(true) { - // FIXME: move from char* to LLVM data structures - Condition = ConditionInit ? strdup(ConditionInit) : nullptr; - Code = CodeInit ? strdup(CodeInit) : nullptr; -} - -Branch::~Branch() { - // FIXME: move from char* to LLVM data structures - free(static_cast<void *>(const_cast<char *>(Condition))); - free(static_cast<void *>(const_cast<char *>(Code))); -} - -// Block - -Block::Block(const char *CodeInit, const char *BranchVarInit) - : Parent(nullptr), Id(-1), IsCheckedMultipleEntry(false) { - // FIXME: move from char* to LLVM data structures - Code = strdup(CodeInit); - BranchVar = BranchVarInit ? strdup(BranchVarInit) : nullptr; -} - -Block::~Block() { - // FIXME: move from char* to LLVM data structures - free(static_cast<void *>(const_cast<char *>(Code))); - free(static_cast<void *>(const_cast<char *>(BranchVar))); -} - -void Block::AddBranchTo(Block *Target, const char *Condition, - const char *Code) { - assert(!contains(BranchesOut, Target) && - "cannot add more than one branch to the same target"); - BranchesOut[Target] = make_unique<Branch>(Condition, Code); -} - -// Relooper - -RelooperAlgorithm::RelooperAlgorithm() - : Root(nullptr), MinSize(false), BlockIdCounter(1), - ShapeIdCounter(0) { // block ID 0 is reserved for clearings -} - -RelooperAlgorithm::~RelooperAlgorithm() { - for (auto Curr : Blocks) - delete Curr; - for (auto Curr : Shapes) - delete Curr; -} - -void RelooperAlgorithm::AddBlock(Block *New, int Id) { - New->Id = Id == -1 ? BlockIdCounter++ : Id; - Blocks.push_back(New); -} - -struct RelooperRecursor { - RelooperAlgorithm *Parent; - RelooperRecursor(RelooperAlgorithm *ParentInit) : Parent(ParentInit) {} -}; - -void RelooperAlgorithm::Calculate(Block *Entry) { - // Scan and optimize the input - struct PreOptimizer : public RelooperRecursor { - PreOptimizer(RelooperAlgorithm *Parent) : RelooperRecursor(Parent) {} - BlockSet Live; - - void FindLive(Block *Root) { - BlockList ToInvestigate; - ToInvestigate.push_back(Root); - while (!ToInvestigate.empty()) { - Block *Curr = ToInvestigate.front(); - ToInvestigate.pop_front(); - if (contains(Live, Curr)) - continue; - Live.insert(Curr); - for (const auto &iter : Curr->BranchesOut) - ToInvestigate.push_back(iter.first); - } - } - - // If a block has multiple entries but no exits, and it is small enough, it - // is useful to split it. A common example is a C++ function where - // everything ends up at a final exit block and does some RAII cleanup. - // Without splitting, we will be forced to introduce labelled loops to - // allow reaching the final block - void SplitDeadEnds() { - unsigned TotalCodeSize = 0; - for (const auto &Curr : Live) { - TotalCodeSize += strlen(Curr->Code); - } - BlockSet Splits; - BlockSet Removed; - for (const auto &Original : Live) { - if (Original->BranchesIn.size() <= 1 || - !Original->BranchesOut.empty()) - continue; // only dead ends, for now - if (contains(Original->BranchesOut, Original)) - continue; // cannot split a looping node - if (strlen(Original->Code) * (Original->BranchesIn.size() - 1) > - TotalCodeSize / RelooperSplittingFactor) - continue; // if splitting increases raw code size by a significant - // amount, abort - // Split the node (for simplicity, we replace all the blocks, even - // though we could have reused the original) - DEBUG(dbgs() << " Splitting '" << Original->Code << "'\n"); - for (const auto &Prior : Original->BranchesIn) { - Block *Split = new Block(Original->Code, Original->BranchVar); - Parent->AddBlock(Split, Original->Id); - Split->BranchesIn.insert(Prior); - std::unique_ptr<Branch> Details; - Details.swap(Prior->BranchesOut[Original]); - Prior->BranchesOut[Split] = make_unique<Branch>(Details->Condition, - Details->Code); - for (const auto &iter : Original->BranchesOut) { - Block *Post = iter.first; - Branch *Details = iter.second.get(); - Split->BranchesOut[Post] = make_unique<Branch>(Details->Condition, - Details->Code); - Post->BranchesIn.insert(Split); - } - Splits.insert(Split); - Removed.insert(Original); - } - for (const auto &iter : Original->BranchesOut) { - Block *Post = iter.first; - Post->BranchesIn.remove(Original); - } - } - for (const auto &iter : Splits) - Live.insert(iter); - for (const auto &iter : Removed) - Live.remove(iter); - } - }; - PreOptimizer Pre(this); - Pre.FindLive(Entry); - - // Add incoming branches from live blocks, ignoring dead code - for (unsigned i = 0; i < Blocks.size(); i++) { - Block *Curr = Blocks[i]; - if (!contains(Pre.Live, Curr)) - continue; - for (const auto &iter : Curr->BranchesOut) - iter.first->BranchesIn.insert(Curr); - } - - if (!MinSize) - Pre.SplitDeadEnds(); - - // Recursively process the graph - - struct Analyzer : public RelooperRecursor { - Analyzer(RelooperAlgorithm *Parent) : RelooperRecursor(Parent) {} - - // Add a shape to the list of shapes in this Relooper calculation - void Notice(Shape *New) { - New->Id = Parent->ShapeIdCounter++; - Parent->Shapes.push_back(New); - } - - // Create a list of entries from a block. If LimitTo is provided, only - // results in that set will appear - void GetBlocksOut(Block *Source, BlockSet &Entries, - BlockSet *LimitTo = nullptr) { - for (const auto &iter : Source->BranchesOut) - if (!LimitTo || contains(*LimitTo, iter.first)) - Entries.insert(iter.first); - } - - // Converts/processes all branchings to a specific target - void Solipsize(Block *Target, Branch::FlowType Type, Shape *Ancestor, - BlockSet &From) { - DEBUG(dbgs() << " Solipsize '" << Target->Code << "' type " << Type - << "\n"); - for (auto iter = Target->BranchesIn.begin(); - iter != Target->BranchesIn.end();) { - Block *Prior = *iter; - if (!contains(From, Prior)) { - iter++; - continue; - } - std::unique_ptr<Branch> PriorOut; - PriorOut.swap(Prior->BranchesOut[Target]); - PriorOut->Ancestor = Ancestor; - PriorOut->Type = Type; - if (MultipleShape *Multiple = dyn_cast<MultipleShape>(Ancestor)) - Multiple->Breaks++; // We are breaking out of this Multiple, so need a - // loop - iter++; // carefully increment iter before erasing - Target->BranchesIn.remove(Prior); - Target->ProcessedBranchesIn.insert(Prior); - Prior->ProcessedBranchesOut[Target].swap(PriorOut); - } - } - - Shape *MakeSimple(BlockSet &Blocks, Block *Inner, BlockSet &NextEntries) { - DEBUG(dbgs() << " MakeSimple inner block '" << Inner->Code << "'\n"); - SimpleShape *Simple = new SimpleShape; - Notice(Simple); - Simple->Inner = Inner; - Inner->Parent = Simple; - if (Blocks.size() > 1) { - Blocks.remove(Inner); - GetBlocksOut(Inner, NextEntries, &Blocks); - BlockSet JustInner; - JustInner.insert(Inner); - for (const auto &iter : NextEntries) - Solipsize(iter, Branch::Direct, Simple, JustInner); - } - return Simple; - } - - Shape *MakeLoop(BlockSet &Blocks, BlockSet &Entries, - BlockSet &NextEntries) { - // Find the inner blocks in this loop. Proceed backwards from the entries - // until - // you reach a seen block, collecting as you go. - BlockSet InnerBlocks; - BlockSet Queue = Entries; - while (!Queue.empty()) { - Block *Curr = *(Queue.begin()); - Queue.remove(*Queue.begin()); - if (!contains(InnerBlocks, Curr)) { - // This element is new, mark it as inner and remove from outer - InnerBlocks.insert(Curr); - Blocks.remove(Curr); - // Add the elements prior to it - for (const auto &iter : Curr->BranchesIn) - Queue.insert(iter); - } - } - assert(!InnerBlocks.empty()); - - for (const auto &Curr : InnerBlocks) { - for (const auto &iter : Curr->BranchesOut) { - Block *Possible = iter.first; - if (!contains(InnerBlocks, Possible)) - NextEntries.insert(Possible); - } - } - - LoopShape *Loop = new LoopShape(); - Notice(Loop); - - // Solipsize the loop, replacing with break/continue and marking branches - // as Processed (will not affect later calculations) - // A. Branches to the loop entries become a continue to this shape - for (const auto &iter : Entries) - Solipsize(iter, Branch::Continue, Loop, InnerBlocks); - // B. Branches to outside the loop (a next entry) become breaks on this - // shape - for (const auto &iter : NextEntries) - Solipsize(iter, Branch::Break, Loop, InnerBlocks); - // Finish up - Shape *Inner = Process(InnerBlocks, Entries, nullptr); - Loop->Inner = Inner; - return Loop; - } - - // For each entry, find the independent group reachable by it. The - // independent group is the entry itself, plus all the blocks it can - // reach that cannot be directly reached by another entry. Note that we - // ignore directly reaching the entry itself by another entry. - // @param Ignore - previous blocks that are irrelevant - void FindIndependentGroups(BlockSet &Entries, - BlockBlockSetMap &IndependentGroups, - BlockSet *Ignore = nullptr) { - typedef std::map<Block *, Block *> BlockBlockMap; - - struct HelperClass { - BlockBlockSetMap &IndependentGroups; - BlockBlockMap Ownership; // For each block, which entry it belongs to. - // We have reached it from there. - - HelperClass(BlockBlockSetMap &IndependentGroupsInit) - : IndependentGroups(IndependentGroupsInit) {} - void InvalidateWithChildren(Block *New) { - // Being in the list means you need to be invalidated - BlockList ToInvalidate; - ToInvalidate.push_back(New); - while (!ToInvalidate.empty()) { - Block *Invalidatee = ToInvalidate.front(); - ToInvalidate.pop_front(); - Block *Owner = Ownership[Invalidatee]; - // Owner may have been invalidated, do not add to - // IndependentGroups! - if (contains(IndependentGroups, Owner)) - IndependentGroups[Owner].remove(Invalidatee); - if (Ownership[Invalidatee]) { // may have been seen before and - // invalidated already - Ownership[Invalidatee] = nullptr; - for (const auto &iter : Invalidatee->BranchesOut) { - Block *Target = iter.first; - BlockBlockMap::iterator Known = Ownership.find(Target); - if (Known != Ownership.end()) { - Block *TargetOwner = Known->second; - if (TargetOwner) - ToInvalidate.push_back(Target); - } - } - } - } - } - }; - HelperClass Helper(IndependentGroups); - - // We flow out from each of the entries, simultaneously. - // When we reach a new block, we add it as belonging to the one we got to - // it from. - // If we reach a new block that is already marked as belonging to someone, - // it is reachable by two entries and is not valid for any of them. - // Remove it and all it can reach that have been visited. - - // Being in the queue means we just added this item, and - // we need to add its children - BlockList Queue; - for (const auto &Entry : Entries) { - Helper.Ownership[Entry] = Entry; - IndependentGroups[Entry].insert(Entry); - Queue.push_back(Entry); - } - while (!Queue.empty()) { - Block *Curr = Queue.front(); - Queue.pop_front(); - Block *Owner = Helper.Ownership[Curr]; // Curr must be in the ownership - // map if we are in the queue - if (!Owner) - continue; // we have been invalidated meanwhile after being reached - // from two entries - // Add all children - for (const auto &iter : Curr->BranchesOut) { - Block *New = iter.first; - BlockBlockMap::iterator Known = Helper.Ownership.find(New); - if (Known == Helper.Ownership.end()) { - // New node. Add it, and put it in the queue - Helper.Ownership[New] = Owner; - IndependentGroups[Owner].insert(New); - Queue.push_back(New); - continue; - } - Block *NewOwner = Known->second; - if (!NewOwner) - continue; // We reached an invalidated node - if (NewOwner != Owner) - // Invalidate this and all reachable that we have seen - we reached - // this from two locations - Helper.InvalidateWithChildren(New); - // otherwise, we have the same owner, so do nothing - } - } - - // Having processed all the interesting blocks, we remain with just one - // potential issue: - // If a->b, and a was invalidated, but then b was later reached by - // someone else, we must invalidate b. To check for this, we go over all - // elements in the independent groups, if an element has a parent which - // does *not* have the same owner, we/ must remove it and all its - // children. - - for (const auto &iter : Entries) { - BlockSet &CurrGroup = IndependentGroups[iter]; - BlockList ToInvalidate; - for (const auto &iter : CurrGroup) { - Block *Child = iter; - for (const auto &iter : Child->BranchesIn) { - Block *Parent = iter; - if (Ignore && contains(*Ignore, Parent)) - continue; - if (Helper.Ownership[Parent] != Helper.Ownership[Child]) - ToInvalidate.push_back(Child); - } - } - while (!ToInvalidate.empty()) { - Block *Invalidatee = ToInvalidate.front(); - ToInvalidate.pop_front(); - Helper.InvalidateWithChildren(Invalidatee); - } - } - - // Remove empty groups - for (const auto &iter : Entries) - if (IndependentGroups[iter].empty()) - IndependentGroups.erase(iter); - } - - Shape *MakeMultiple(BlockSet &Blocks, BlockSet &Entries, - BlockBlockSetMap &IndependentGroups, Shape *Prev, - BlockSet &NextEntries) { - bool Fused = isa<SimpleShape>(Prev); - MultipleShape *Multiple = new MultipleShape(); - Notice(Multiple); - BlockSet CurrEntries; - for (auto &iter : IndependentGroups) { - Block *CurrEntry = iter.first; - BlockSet &CurrBlocks = iter.second; - // Create inner block - CurrEntries.clear(); - CurrEntries.insert(CurrEntry); - for (const auto &CurrInner : CurrBlocks) { - // Remove the block from the remaining blocks - Blocks.remove(CurrInner); - // Find new next entries and fix branches to them - for (auto iter = CurrInner->BranchesOut.begin(); - iter != CurrInner->BranchesOut.end();) { - Block *CurrTarget = iter->first; - auto Next = iter; - Next++; - if (!contains(CurrBlocks, CurrTarget)) { - NextEntries.insert(CurrTarget); - Solipsize(CurrTarget, Branch::Break, Multiple, CurrBlocks); - } - iter = Next; // increment carefully because Solipsize can remove us - } - } - Multiple->InnerMap[CurrEntry->Id] = - Process(CurrBlocks, CurrEntries, nullptr); - // If we are not fused, then our entries will actually be checked - if (!Fused) - CurrEntry->IsCheckedMultipleEntry = true; - } - // Add entries not handled as next entries, they are deferred - for (const auto &Entry : Entries) - if (!contains(IndependentGroups, Entry)) - NextEntries.insert(Entry); - // The multiple has been created, we can decide how to implement it - if (Multiple->InnerMap.size() >= RelooperMultipleSwitchThreshold) { - Multiple->UseSwitch = true; - Multiple->Breaks++; // switch captures breaks - } - return Multiple; - } - - // Main function. - // Process a set of blocks with specified entries, returns a shape - // The Make* functions receive a NextEntries. If they fill it with data, - // those are the entries for the ->Next block on them, and the blocks - // are what remains in Blocks (which Make* modify). In this way - // we avoid recursing on Next (imagine a long chain of Simples, if we - // recursed we could blow the stack). - Shape *Process(BlockSet &Blocks, BlockSet &InitialEntries, Shape *Prev) { - BlockSet *Entries = &InitialEntries; - BlockSet TempEntries[2]; - int CurrTempIndex = 0; - BlockSet *NextEntries; - Shape *Ret = nullptr; - - auto Make = [&](Shape *Temp) { - if (Prev) - Prev->Next = Temp; - if (!Ret) - Ret = Temp; - Prev = Temp; - Entries = NextEntries; - }; - - while (1) { - CurrTempIndex = 1 - CurrTempIndex; - NextEntries = &TempEntries[CurrTempIndex]; - NextEntries->clear(); - - if (Entries->empty()) - return Ret; - if (Entries->size() == 1) { - Block *Curr = *(Entries->begin()); - if (Curr->BranchesIn.empty()) { - // One entry, no looping ==> Simple - Make(MakeSimple(Blocks, Curr, *NextEntries)); - if (NextEntries->empty()) - return Ret; - continue; - } - // One entry, looping ==> Loop - Make(MakeLoop(Blocks, *Entries, *NextEntries)); - if (NextEntries->empty()) - return Ret; - continue; - } - - // More than one entry, try to eliminate through a Multiple groups of - // independent blocks from an entry/ies. It is important to remove - // through multiples as opposed to looping since the former is more - // performant. - BlockBlockSetMap IndependentGroups; - FindIndependentGroups(*Entries, IndependentGroups); - - if (!IndependentGroups.empty()) { - // We can handle a group in a multiple if its entry cannot be reached - // by another group. - // Note that it might be reachable by itself - a loop. But that is - // fine, we will create a loop inside the multiple block (which - // is the performant order to do it). - for (auto iter = IndependentGroups.begin(); - iter != IndependentGroups.end();) { - Block *Entry = iter->first; - BlockSet &Group = iter->second; - auto curr = iter++; // iterate carefully, we may delete - for (BlockSet::iterator iterBranch = Entry->BranchesIn.begin(); - iterBranch != Entry->BranchesIn.end(); iterBranch++) { - Block *Origin = *iterBranch; - if (!contains(Group, Origin)) { - // Reached from outside the group, so we cannot handle this - IndependentGroups.erase(curr); - break; - } - } - } - - // As an optimization, if we have 2 independent groups, and one is a - // small dead end, we can handle only that dead end. - // The other then becomes a Next - without nesting in the code and - // recursion in the analysis. - // TODO: if the larger is the only dead end, handle that too - // TODO: handle >2 groups - // TODO: handle not just dead ends, but also that do not branch to the - // NextEntries. However, must be careful there since we create a - // Next, and that Next can prevent eliminating a break (since we no - // longer naturally reach the same place), which may necessitate a - // one-time loop, which makes the unnesting pointless. - if (IndependentGroups.size() == 2) { - // Find the smaller one - auto iter = IndependentGroups.begin(); - Block *SmallEntry = iter->first; - auto SmallSize = iter->second.size(); - iter++; - Block *LargeEntry = iter->first; - auto LargeSize = iter->second.size(); - if (SmallSize != LargeSize) { // ignore the case where they are - // identical - keep things symmetrical - // there - if (SmallSize > LargeSize) { - Block *Temp = SmallEntry; - SmallEntry = LargeEntry; - LargeEntry = Temp; // Note: we did not flip the Sizes too, they - // are now invalid. TODO: use the smaller - // size as a limit? - } - // Check if dead end - bool DeadEnd = true; - BlockSet &SmallGroup = IndependentGroups[SmallEntry]; - for (const auto &Curr : SmallGroup) { - for (const auto &iter : Curr->BranchesOut) { - Block *Target = iter.first; - if (!contains(SmallGroup, Target)) { - DeadEnd = false; - break; - } - } - if (!DeadEnd) - break; - } - if (DeadEnd) - IndependentGroups.erase(LargeEntry); - } - } - - if (!IndependentGroups.empty()) - // Some groups removable ==> Multiple - Make(MakeMultiple(Blocks, *Entries, IndependentGroups, Prev, - *NextEntries)); - if (NextEntries->empty()) - return Ret; - continue; - } - // No independent groups, must be loopable ==> Loop - Make(MakeLoop(Blocks, *Entries, *NextEntries)); - if (NextEntries->empty()) - return Ret; - continue; - } - } - }; - - // Main - - BlockSet AllBlocks; - for (const auto &Curr : Pre.Live) { - AllBlocks.insert(Curr); - } - - BlockSet Entries; - Entries.insert(Entry); - Root = Analyzer(this).Process(AllBlocks, Entries, nullptr); - assert(Root); - - /// - /// Relooper post-optimizer - /// - struct PostOptimizer { - RelooperAlgorithm *Parent; - std::stack<Shape *> LoopStack; - - PostOptimizer(RelooperAlgorithm *ParentInit) : Parent(ParentInit) {} - - void ShapeSwitch(Shape* var, - std::function<void (SimpleShape*)> simple, - std::function<void (MultipleShape*)> multiple, - std::function<void (LoopShape*)> loop) { - switch (var->getKind()) { - case Shape::SK_Simple: { - simple(cast<SimpleShape>(var)); - break; - } - case Shape::SK_Multiple: { - multiple(cast<MultipleShape>(var)); - break; - } - case Shape::SK_Loop: { - loop(cast<LoopShape>(var)); - break; - } - } - } - - // Find the blocks that natural control flow can get us directly to, or - // through a multiple that we ignore - void FollowNaturalFlow(Shape *S, BlockSet &Out) { - ShapeSwitch(S, [&](SimpleShape* Simple) { - Out.insert(Simple->Inner); - }, [&](MultipleShape* Multiple) { - for (const auto &iter : Multiple->InnerMap) { - FollowNaturalFlow(iter.second, Out); - } - FollowNaturalFlow(Multiple->Next, Out); - }, [&](LoopShape* Loop) { - FollowNaturalFlow(Loop->Inner, Out); - }); - } - - void FindNaturals(Shape *Root, Shape *Otherwise = nullptr) { - if (Root->Next) { - Root->Natural = Root->Next; - FindNaturals(Root->Next, Otherwise); - } else { - Root->Natural = Otherwise; - } - - ShapeSwitch(Root, [](SimpleShape* Simple) { - }, [&](MultipleShape* Multiple) { - for (const auto &iter : Multiple->InnerMap) { - FindNaturals(iter.second, Root->Natural); - } - }, [&](LoopShape* Loop){ - FindNaturals(Loop->Inner, Loop->Inner); - }); - } - - // Remove unneeded breaks and continues. - // A flow operation is trivially unneeded if the shape we naturally get to - // by normal code execution is the same as the flow forces us to. - void RemoveUnneededFlows(Shape *Root, Shape *Natural = nullptr, - LoopShape *LastLoop = nullptr, - unsigned Depth = 0) { - BlockSet NaturalBlocks; - FollowNaturalFlow(Natural, NaturalBlocks); - Shape *Next = Root; - while (Next) { - Root = Next; - Next = nullptr; - ShapeSwitch( - Root, - [&](SimpleShape* Simple) { - if (Simple->Inner->BranchVar) - LastLoop = - nullptr; // a switch clears out the loop (TODO: only for - // breaks, not continue) - - if (Simple->Next) { - if (!Simple->Inner->BranchVar && - Simple->Inner->ProcessedBranchesOut.size() == 2 && - Depth < RelooperNestingLimit) { - // If there is a next block, we already know at Simple - // creation time to make direct branches, and we can do - // nothing more in general. But, we try to optimize the - // case of a break and a direct: This would normally be - // if (break?) { break; } .. - // but if we make sure to nest the else, we can save the - // break, - // if (!break?) { .. } - // This is also better because the more canonical nested - // form is easier to further optimize later. The - // downside is more nesting, which adds to size in builds with - // whitespace. - // Note that we avoid switches, as it complicates control flow - // and is not relevant for the common case we optimize here. - bool Found = false; - bool Abort = false; - for (const auto &iter : Simple->Inner->ProcessedBranchesOut) { - Block *Target = iter.first; - Branch *Details = iter.second.get(); - if (Details->Type == Branch::Break) { - Found = true; - if (!contains(NaturalBlocks, Target)) - Abort = true; - } else if (Details->Type != Branch::Direct) - Abort = true; - } - if (Found && !Abort) { - for (const auto &iter : Simple->Inner->ProcessedBranchesOut) { - Branch *Details = iter.second.get(); - if (Details->Type == Branch::Break) { - Details->Type = Branch::Direct; - if (MultipleShape *Multiple = - dyn_cast<MultipleShape>(Details->Ancestor)) - Multiple->Breaks--; - } else { - assert(Details->Type == Branch::Direct); - Details->Type = Branch::Nested; - } - } - } - Depth++; // this optimization increases depth, for us and all - // our next chain (i.e., until this call returns) - } - Next = Simple->Next; - } else { - // If there is no next then Natural is where we will - // go to by doing nothing, so we can potentially optimize some - // branches to direct. - for (const auto &iter : Simple->Inner->ProcessedBranchesOut) { - Block *Target = iter.first; - Branch *Details = iter.second.get(); - if (Details->Type != Branch::Direct && - contains(NaturalBlocks, - Target)) { // note: cannot handle split blocks - Details->Type = Branch::Direct; - if (MultipleShape *Multiple = - dyn_cast<MultipleShape>(Details->Ancestor)) - Multiple->Breaks--; - } else if (Details->Type == Branch::Break && LastLoop && - LastLoop->Natural == Details->Ancestor->Natural) { - // it is important to simplify breaks, as simpler breaks - // enable other optimizations - Details->Labeled = false; - if (MultipleShape *Multiple = - dyn_cast<MultipleShape>(Details->Ancestor)) - Multiple->Breaks--; - } - } - } - }, [&](MultipleShape* Multiple) - { - for (const auto &iter : Multiple->InnerMap) { - RemoveUnneededFlows(iter.second, Multiple->Next, - Multiple->Breaks ? nullptr : LastLoop, - Depth + 1); - } - Next = Multiple->Next; - }, [&](LoopShape* Loop) - { - RemoveUnneededFlows(Loop->Inner, Loop->Inner, Loop, Depth + 1); - Next = Loop->Next; - }); - } - } - - // After we know which loops exist, we can calculate which need to be - // labeled - void FindLabeledLoops(Shape *Root) { - Shape *Next = Root; - while (Next) { - Root = Next; - Next = nullptr; - - ShapeSwitch( - Root, - [&](SimpleShape *Simple) { - MultipleShape *Fused = dyn_cast<MultipleShape>(Root->Next); - // If we are fusing a Multiple with a loop into this Simple, then - // visit it now - if (Fused && Fused->Breaks) - LoopStack.push(Fused); - if (Simple->Inner->BranchVar) - LoopStack.push(nullptr); // a switch means breaks are now useless, - // push a dummy - if (Fused) { - if (Fused->UseSwitch) - LoopStack.push(nullptr); // a switch means breaks are now - // useless, push a dummy - for (const auto &iter : Fused->InnerMap) { - FindLabeledLoops(iter.second); - } - } - for (const auto &iter : Simple->Inner->ProcessedBranchesOut) { - Branch *Details = iter.second.get(); - if (Details->Type == Branch::Break || - Details->Type == Branch::Continue) { - assert(!LoopStack.empty()); - if (Details->Ancestor != LoopStack.top() && Details->Labeled) { - if (MultipleShape *Multiple = - dyn_cast<MultipleShape>(Details->Ancestor)) { - Multiple->Labeled = true; - } else { - LoopShape *Loop = cast<LoopShape>(Details->Ancestor); - Loop->Labeled = true; - } - } else { - Details->Labeled = false; - } - } - if (Fused && Fused->UseSwitch) - LoopStack.pop(); - if (Simple->Inner->BranchVar) - LoopStack.pop(); - if (Fused && Fused->Breaks) - LoopStack.pop(); - if (Fused) - Next = Fused->Next; - else - Next = Root->Next; - } - } - , [&](MultipleShape* Multiple) { - if (Multiple->Breaks) - LoopStack.push(Multiple); - for (const auto &iter : Multiple->InnerMap) - FindLabeledLoops(iter.second); - if (Multiple->Breaks) - LoopStack.pop(); - Next = Root->Next; - } - , [&](LoopShape* Loop) { - LoopStack.push(Loop); - FindLabeledLoops(Loop->Inner); - LoopStack.pop(); - Next = Root->Next; - }); - } - } - - void Process(Shape * Root) { - FindNaturals(Root); - RemoveUnneededFlows(Root); - FindLabeledLoops(Root); - } - }; - - PostOptimizer(this).Process(Root); -} diff --git a/gnu/llvm/lib/Target/WebAssembly/Relooper.h b/gnu/llvm/lib/Target/WebAssembly/Relooper.h deleted file mode 100644 index 7c564de82f3..00000000000 --- a/gnu/llvm/lib/Target/WebAssembly/Relooper.h +++ /dev/null @@ -1,186 +0,0 @@ -//===-- Relooper.h - Top-level interface for WebAssembly ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===-------------------------------------------------------------------===// -/// -/// \file -/// \brief This defines an optimized C++ implemention of the Relooper -/// algorithm, originally developed as part of Emscripten, which -/// generates a structured AST from arbitrary control flow. -/// -//===-------------------------------------------------------------------===// - -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/Support/Casting.h" - -#include <cassert> -#include <cstdarg> -#include <cstdio> -#include <deque> -#include <list> -#include <map> -#include <memory> -#include <set> - -namespace llvm { - -namespace Relooper { - -struct Block; -struct Shape; - -/// -/// Info about a branching from one block to another -/// -struct Branch { - enum FlowType { - Direct = 0, // We will directly reach the right location through other - // means, no need for continue or break - Break = 1, - Continue = 2, - Nested = 3 // This code is directly reached, but we must be careful to - // ensure it is nested in an if - it is not reached - // unconditionally, other code paths exist alongside it that we need to make - // sure do not intertwine - }; - Shape - *Ancestor; // If not nullptr, this shape is the relevant one for purposes - // of getting to the target block. We break or continue on it - Branch::FlowType - Type; // If Ancestor is not nullptr, this says whether to break or - // continue - bool Labeled; // If a break or continue, whether we need to use a label - const char *Condition; // The condition for which we branch. For example, - // "my_var == 1". Conditions are checked one by one. - // One of the conditions should have nullptr as the - // condition, in which case it is the default - // FIXME: move from char* to LLVM data structures - const char *Code; // If provided, code that is run right before the branch is - // taken. This is useful for phis - // FIXME: move from char* to LLVM data structures - - Branch(const char *ConditionInit, const char *CodeInit = nullptr); - ~Branch(); -}; - -typedef SetVector<Block *> BlockSet; -typedef MapVector<Block *, Branch *> BlockBranchMap; -typedef MapVector<Block *, std::unique_ptr<Branch>> OwningBlockBranchMap; - -/// -/// Represents a basic block of code - some instructions that end with a -/// control flow modifier (a branch, return or throw). -/// -struct Block { - // Branches become processed after we finish the shape relevant to them. For - // example, when we recreate a loop, branches to the loop start become - // continues and are now processed. When we calculate what shape to generate - // from a set of blocks, we ignore processed branches. Blocks own the Branch - // objects they use, and destroy them when done. - OwningBlockBranchMap BranchesOut; - BlockSet BranchesIn; - OwningBlockBranchMap ProcessedBranchesOut; - BlockSet ProcessedBranchesIn; - Shape *Parent; // The shape we are directly inside - int Id; // A unique identifier, defined when added to relooper. Note that this - // uniquely identifies a *logical* block - if we split it, the two - // instances have the same content *and* the same Id - const char *Code; // The string representation of the code in this block. - // Owning pointer (we copy the input) - // FIXME: move from char* to LLVM data structures - const char *BranchVar; // A variable whose value determines where we go; if - // this is not nullptr, emit a switch on that variable - // FIXME: move from char* to LLVM data structures - bool IsCheckedMultipleEntry; // If true, we are a multiple entry, so reaching - // us requires setting the label variable - - Block(const char *CodeInit, const char *BranchVarInit); - ~Block(); - - void AddBranchTo(Block *Target, const char *Condition, - const char *Code = nullptr); -}; - -/// -/// Represents a structured control flow shape -/// -struct Shape { - int Id; // A unique identifier. Used to identify loops, labels are Lx where x - // is the Id. Defined when added to relooper - Shape *Next; // The shape that will appear in the code right after this one - Shape *Natural; // The shape that control flow gets to naturally (if there is - // Next, then this is Next) - - /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.) - enum ShapeKind { SK_Simple, SK_Multiple, SK_Loop }; - -private: - ShapeKind Kind; - -public: - ShapeKind getKind() const { return Kind; } - - Shape(ShapeKind KindInit) : Id(-1), Next(nullptr), Kind(KindInit) {} -}; - -/// -/// Simple: No control flow at all, just instructions. -/// -struct SimpleShape : public Shape { - Block *Inner; - - SimpleShape() : Shape(SK_Simple), Inner(nullptr) {} - - static bool classof(const Shape *S) { return S->getKind() == SK_Simple; } -}; - -/// -/// A shape that may be implemented with a labeled loop. -/// -struct LabeledShape : public Shape { - bool Labeled; // If we have a loop, whether it needs to be labeled - - LabeledShape(ShapeKind KindInit) : Shape(KindInit), Labeled(false) {} -}; - -// Blocks with the same id were split and are identical, so we just care about -// ids in Multiple entries -typedef std::map<int, Shape *> IdShapeMap; - -/// -/// Multiple: A shape with more than one entry. If the next block to -/// be entered is among them, we run it and continue to -/// the next shape, otherwise we continue immediately to the -/// next shape. -/// -struct MultipleShape : public LabeledShape { - IdShapeMap InnerMap; // entry block ID -> shape - int Breaks; // If we have branches on us, we need a loop (or a switch). This - // is a counter of requirements, - // if we optimize it to 0, the loop is unneeded - bool UseSwitch; // Whether to switch on label as opposed to an if-else chain - - MultipleShape() : LabeledShape(SK_Multiple), Breaks(0), UseSwitch(false) {} - - static bool classof(const Shape *S) { return S->getKind() == SK_Multiple; } -}; - -/// -/// Loop: An infinite loop. -/// -struct LoopShape : public LabeledShape { - Shape *Inner; - - LoopShape() : LabeledShape(SK_Loop), Inner(nullptr) {} - - static bool classof(const Shape *S) { return S->getKind() == SK_Loop; } -}; - -} // namespace Relooper - -} // namespace llvm diff --git a/gnu/llvm/lib/Target/WebAssembly/TargetInfo/Makefile b/gnu/llvm/lib/Target/WebAssembly/TargetInfo/Makefile deleted file mode 100644 index b021eb6d945..00000000000 --- a/gnu/llvm/lib/Target/WebAssembly/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/WebAssembly/TargetInfo/Makefile ----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMWebAssemblyInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/WebAssembly/WebAssemblyPEI.cpp b/gnu/llvm/lib/Target/WebAssembly/WebAssemblyPEI.cpp deleted file mode 100644 index d570d426611..00000000000 --- a/gnu/llvm/lib/Target/WebAssembly/WebAssemblyPEI.cpp +++ /dev/null @@ -1,1066 +0,0 @@ -//===-- WebAssemblyPEI.cpp - Insert Prolog/Epilog code in function --===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass is responsible for finalizing the functions frame layout, saving -// callee saved registers, and for emitting prolog & epilog code for the -// function. -// -// This pass must be run after register allocation. After this pass is -// executed, it is illegal to construct MO_FrameIndex operands. -// -// This is a copy of lib/CodeGen/PrologEpilogInserter.cpp except that it does -// not assert that all virtual registers are gone (because WebAssembly currently -// uses virtual rather than physical registers), and only runs -// MRI.clearVirtRegs() if scavenging happened (which it never does). It also -// uses a different class name so it can be registered via INITIALIZE_PASS. -// It is otherwise unmodified, so any changes to the target-independent PEI -// can be easily applied. -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/IndexedMap.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineLoopInfo.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/RegisterScavenging.h" -#include "llvm/CodeGen/StackProtector.h" -#include "llvm/CodeGen/WinEHFuncInfo.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetFrameLowering.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Target/TargetSubtargetInfo.h" -#include <climits> - -using namespace llvm; - -#define DEBUG_TYPE "pei" -namespace llvm { -void initializeWasmPEIPass(PassRegistry&); -} -namespace { -class WasmPEI : public MachineFunctionPass { -public: - static char ID; - WasmPEI() : MachineFunctionPass(ID) { - initializeWasmPEIPass(*PassRegistry::getPassRegistry()); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// runOnMachineFunction - Insert prolog/epilog code and replace abstract - /// frame indexes with appropriate references. - /// - bool runOnMachineFunction(MachineFunction &Fn) override; - -private: - RegScavenger *RS; - - // MinCSFrameIndex, MaxCSFrameIndex - Keeps the range of callee saved - // stack frame indexes. - unsigned MinCSFrameIndex, MaxCSFrameIndex; - - // Save and Restore blocks of the current function. Typically there is a - // single save block, unless Windows EH funclets are involved. - SmallVector<MachineBasicBlock *, 1> SaveBlocks; - SmallVector<MachineBasicBlock *, 4> RestoreBlocks; - - // Flag to control whether to use the register scavenger to resolve - // frame index materialization registers. Set according to - // TRI->requiresFrameIndexScavenging() for the current function. - bool FrameIndexVirtualScavenging; - - void calculateSets(MachineFunction &Fn); - void calculateCallsInformation(MachineFunction &Fn); - void assignCalleeSavedSpillSlots(MachineFunction &Fn, - const BitVector &SavedRegs); - void insertCSRSpillsAndRestores(MachineFunction &Fn); - void calculateFrameObjectOffsets(MachineFunction &Fn); - void replaceFrameIndices(MachineFunction &Fn); - void replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn, - int &SPAdj); - void scavengeFrameVirtualRegs(MachineFunction &Fn); - void insertPrologEpilogCode(MachineFunction &Fn); -}; -} // namespace - -char WasmPEI::ID = 0; - -namespace llvm { -FunctionPass *createWebAssemblyPEI() { - return new WasmPEI(); -} -} - -static cl::opt<unsigned> -WarnStackSize("wasm-warn-stack-size", cl::Hidden, cl::init((unsigned)-1), - cl::desc("Warn for stack size bigger than the given" - " number")); - -INITIALIZE_PASS_BEGIN(WasmPEI, "wasmprologepilog", - "Wasm Prologue/Epilogue Insertion", false, false) -INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) -INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) -INITIALIZE_PASS_DEPENDENCY(StackProtector) -INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) -INITIALIZE_PASS_END(WasmPEI, "wasmprologepilog", - "Wasm Prologue/Epilogue Insertion & Frame Finalization", - false, false) - -STATISTIC(NumScavengedRegs, "Number of frame index regs scavenged"); -STATISTIC(NumBytesStackSpace, - "Number of bytes used for stack in all functions"); - -void WasmPEI::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - AU.addPreserved<MachineLoopInfo>(); - AU.addPreserved<MachineDominatorTree>(); - AU.addRequired<StackProtector>(); - AU.addRequired<TargetPassConfig>(); - MachineFunctionPass::getAnalysisUsage(AU); -} - -/// Compute the set of return blocks -void WasmPEI::calculateSets(MachineFunction &Fn) { - const MachineFrameInfo *MFI = Fn.getFrameInfo(); - - // Even when we do not change any CSR, we still want to insert the - // prologue and epilogue of the function. - // So set the save points for those. - - // Use the points found by shrink-wrapping, if any. - if (MFI->getSavePoint()) { - SaveBlocks.push_back(MFI->getSavePoint()); - assert(MFI->getRestorePoint() && "Both restore and save must be set"); - MachineBasicBlock *RestoreBlock = MFI->getRestorePoint(); - // If RestoreBlock does not have any successor and is not a return block - // then the end point is unreachable and we do not need to insert any - // epilogue. - if (!RestoreBlock->succ_empty() || RestoreBlock->isReturnBlock()) - RestoreBlocks.push_back(RestoreBlock); - return; - } - - // Save refs to entry and return blocks. - SaveBlocks.push_back(&Fn.front()); - for (MachineBasicBlock &MBB : Fn) { - if (MBB.isEHFuncletEntry()) - SaveBlocks.push_back(&MBB); - if (MBB.isReturnBlock()) - RestoreBlocks.push_back(&MBB); - } -} - -/// StackObjSet - A set of stack object indexes -typedef SmallSetVector<int, 8> StackObjSet; - -/// runOnMachineFunction - Insert prolog/epilog code and replace abstract -/// frame indexes with appropriate references. -/// -bool WasmPEI::runOnMachineFunction(MachineFunction &Fn) { - const Function* F = Fn.getFunction(); - const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo(); - const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); - - // LOCALMOD: assert removed from target-independent PEI - //assert(!Fn.getRegInfo().getNumVirtRegs() && "Regalloc must assign all vregs"); - - RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : nullptr; - FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn); - - // Calculate the MaxCallFrameSize and AdjustsStack variables for the - // function's frame information. Also eliminates call frame pseudo - // instructions. - calculateCallsInformation(Fn); - - // Determine which of the registers in the callee save list should be saved. - BitVector SavedRegs; - TFI->determineCalleeSaves(Fn, SavedRegs, RS); - - // Insert spill code for any callee saved registers that are modified. - assignCalleeSavedSpillSlots(Fn, SavedRegs); - - // Determine placement of CSR spill/restore code: - // place all spills in the entry block, all restores in return blocks. - calculateSets(Fn); - - // Add the code to save and restore the callee saved registers. - if (!F->hasFnAttribute(Attribute::Naked)) - insertCSRSpillsAndRestores(Fn); - - // Allow the target machine to make final modifications to the function - // before the frame layout is finalized. - TFI->processFunctionBeforeFrameFinalized(Fn, RS); - - // Calculate actual frame offsets for all abstract stack objects... - calculateFrameObjectOffsets(Fn); - - // Add prolog and epilog code to the function. This function is required - // to align the stack frame as necessary for any stack variables or - // called functions. Because of this, calculateCalleeSavedRegisters() - // must be called before this function in order to set the AdjustsStack - // and MaxCallFrameSize variables. - if (!F->hasFnAttribute(Attribute::Naked)) - insertPrologEpilogCode(Fn); - - // Replace all MO_FrameIndex operands with physical register references - // and actual offsets. - // - replaceFrameIndices(Fn); - - // If register scavenging is needed, as we've enabled doing it as a - // post-pass, scavenge the virtual registers that frame index elimination - // inserted. - if (TRI->requiresRegisterScavenging(Fn) && FrameIndexVirtualScavenging) { - scavengeFrameVirtualRegs(Fn); - // Clear any vregs created by virtual scavenging. - // LOCALMOD: made this call conditional with scavengeFrameVirtualregs() - Fn.getRegInfo().clearVirtRegs(); - } - - // Warn on stack size when we exceeds the given limit. - MachineFrameInfo *MFI = Fn.getFrameInfo(); - uint64_t StackSize = MFI->getStackSize(); - if (WarnStackSize.getNumOccurrences() > 0 && WarnStackSize < StackSize) { - DiagnosticInfoStackSize DiagStackSize(*F, StackSize); - F->getContext().diagnose(DiagStackSize); - } - - delete RS; - SaveBlocks.clear(); - RestoreBlocks.clear(); - return true; -} - -/// calculateCallsInformation - Calculate the MaxCallFrameSize and AdjustsStack -/// variables for the function's frame information and eliminate call frame -/// pseudo instructions. -void WasmPEI::calculateCallsInformation(MachineFunction &Fn) { - const TargetInstrInfo &TII = *Fn.getSubtarget().getInstrInfo(); - const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); - MachineFrameInfo *MFI = Fn.getFrameInfo(); - - unsigned MaxCallFrameSize = 0; - bool AdjustsStack = MFI->adjustsStack(); - - // Get the function call frame set-up and tear-down instruction opcode - unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode(); - unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode(); - - // Early exit for targets which have no call frame setup/destroy pseudo - // instructions. - if (FrameSetupOpcode == ~0u && FrameDestroyOpcode == ~0u) - return; - - std::vector<MachineBasicBlock::iterator> FrameSDOps; - for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) - for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) - if (I->getOpcode() == FrameSetupOpcode || - I->getOpcode() == FrameDestroyOpcode) { - assert(I->getNumOperands() >= 1 && "Call Frame Setup/Destroy Pseudo" - " instructions should have a single immediate argument!"); - unsigned Size = I->getOperand(0).getImm(); - if (Size > MaxCallFrameSize) MaxCallFrameSize = Size; - AdjustsStack = true; - FrameSDOps.push_back(I); - } else if (I->isInlineAsm()) { - // Some inline asm's need a stack frame, as indicated by operand 1. - unsigned ExtraInfo = I->getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); - if (ExtraInfo & InlineAsm::Extra_IsAlignStack) - AdjustsStack = true; - } - - MFI->setAdjustsStack(AdjustsStack); - MFI->setMaxCallFrameSize(MaxCallFrameSize); - - for (std::vector<MachineBasicBlock::iterator>::iterator - i = FrameSDOps.begin(), e = FrameSDOps.end(); i != e; ++i) { - MachineBasicBlock::iterator I = *i; - - // If call frames are not being included as part of the stack frame, and - // the target doesn't indicate otherwise, remove the call frame pseudos - // here. The sub/add sp instruction pairs are still inserted, but we don't - // need to track the SP adjustment for frame index elimination. - if (TFI->canSimplifyCallFramePseudos(Fn)) - TFI->eliminateCallFramePseudoInstr(Fn, *I->getParent(), I); - } -} - -void WasmPEI::assignCalleeSavedSpillSlots(MachineFunction &F, - const BitVector &SavedRegs) { - // These are used to keep track the callee-save area. Initialize them. - MinCSFrameIndex = INT_MAX; - MaxCSFrameIndex = 0; - - if (SavedRegs.empty()) - return; - - const TargetRegisterInfo *RegInfo = F.getSubtarget().getRegisterInfo(); - const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&F); - - std::vector<CalleeSavedInfo> CSI; - for (unsigned i = 0; CSRegs[i]; ++i) { - unsigned Reg = CSRegs[i]; - if (SavedRegs.test(Reg)) - CSI.push_back(CalleeSavedInfo(Reg)); - } - - const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering(); - MachineFrameInfo *MFI = F.getFrameInfo(); - if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI)) { - // If target doesn't implement this, use generic code. - - if (CSI.empty()) - return; // Early exit if no callee saved registers are modified! - - unsigned NumFixedSpillSlots; - const TargetFrameLowering::SpillSlot *FixedSpillSlots = - TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots); - - // Now that we know which registers need to be saved and restored, allocate - // stack slots for them. - for (std::vector<CalleeSavedInfo>::iterator I = CSI.begin(), E = CSI.end(); - I != E; ++I) { - unsigned Reg = I->getReg(); - const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg); - - int FrameIdx; - if (RegInfo->hasReservedSpillSlot(F, Reg, FrameIdx)) { - I->setFrameIdx(FrameIdx); - continue; - } - - // Check to see if this physreg must be spilled to a particular stack slot - // on this target. - const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots; - while (FixedSlot != FixedSpillSlots + NumFixedSpillSlots && - FixedSlot->Reg != Reg) - ++FixedSlot; - - if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { - // Nope, just spill it anywhere convenient. - unsigned Align = RC->getAlignment(); - unsigned StackAlign = TFI->getStackAlignment(); - - // We may not be able to satisfy the desired alignment specification of - // the TargetRegisterClass if the stack alignment is smaller. Use the - // min. - Align = std::min(Align, StackAlign); - FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true); - if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx; - if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx; - } else { - // Spill it to the stack where we must. - FrameIdx = - MFI->CreateFixedSpillStackObject(RC->getSize(), FixedSlot->Offset); - } - - I->setFrameIdx(FrameIdx); - } - } - - MFI->setCalleeSavedInfo(CSI); -} - -/// Helper function to update the liveness information for the callee-saved -/// registers. -static void updateLiveness(MachineFunction &MF) { - MachineFrameInfo *MFI = MF.getFrameInfo(); - // Visited will contain all the basic blocks that are in the region - // where the callee saved registers are alive: - // - Anything that is not Save or Restore -> LiveThrough. - // - Save -> LiveIn. - // - Restore -> LiveOut. - // The live-out is not attached to the block, so no need to keep - // Restore in this set. - SmallPtrSet<MachineBasicBlock *, 8> Visited; - SmallVector<MachineBasicBlock *, 8> WorkList; - MachineBasicBlock *Entry = &MF.front(); - MachineBasicBlock *Save = MFI->getSavePoint(); - - if (!Save) - Save = Entry; - - if (Entry != Save) { - WorkList.push_back(Entry); - Visited.insert(Entry); - } - Visited.insert(Save); - - MachineBasicBlock *Restore = MFI->getRestorePoint(); - if (Restore) - // By construction Restore cannot be visited, otherwise it - // means there exists a path to Restore that does not go - // through Save. - WorkList.push_back(Restore); - - while (!WorkList.empty()) { - const MachineBasicBlock *CurBB = WorkList.pop_back_val(); - // By construction, the region that is after the save point is - // dominated by the Save and post-dominated by the Restore. - if (CurBB == Save && Save != Restore) - continue; - // Enqueue all the successors not already visited. - // Those are by construction either before Save or after Restore. - for (MachineBasicBlock *SuccBB : CurBB->successors()) - if (Visited.insert(SuccBB).second) - WorkList.push_back(SuccBB); - } - - const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); - - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - for (MachineBasicBlock *MBB : Visited) { - MCPhysReg Reg = CSI[i].getReg(); - // Add the callee-saved register as live-in. - // It's killed at the spill. - if (!MBB->isLiveIn(Reg)) - MBB->addLiveIn(Reg); - } - } -} - -/// insertCSRSpillsAndRestores - Insert spill and restore code for -/// callee saved registers used in the function. -/// -void WasmPEI::insertCSRSpillsAndRestores(MachineFunction &Fn) { - // Get callee saved register information. - MachineFrameInfo *MFI = Fn.getFrameInfo(); - const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); - - MFI->setCalleeSavedInfoValid(true); - - // Early exit if no callee saved registers are modified! - if (CSI.empty()) - return; - - const TargetInstrInfo &TII = *Fn.getSubtarget().getInstrInfo(); - const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); - const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo(); - MachineBasicBlock::iterator I; - - // Spill using target interface. - for (MachineBasicBlock *SaveBlock : SaveBlocks) { - I = SaveBlock->begin(); - if (!TFI->spillCalleeSavedRegisters(*SaveBlock, I, CSI, TRI)) { - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - // Insert the spill to the stack frame. - unsigned Reg = CSI[i].getReg(); - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(*SaveBlock, I, Reg, true, CSI[i].getFrameIdx(), - RC, TRI); - } - } - // Update the live-in information of all the blocks up to the save point. - updateLiveness(Fn); - } - - // Restore using target interface. - for (MachineBasicBlock *MBB : RestoreBlocks) { - I = MBB->end(); - - // Skip over all terminator instructions, which are part of the return - // sequence. - MachineBasicBlock::iterator I2 = I; - while (I2 != MBB->begin() && (--I2)->isTerminator()) - I = I2; - - bool AtStart = I == MBB->begin(); - MachineBasicBlock::iterator BeforeI = I; - if (!AtStart) - --BeforeI; - - // Restore all registers immediately before the return and any - // terminators that precede it. - if (!TFI->restoreCalleeSavedRegisters(*MBB, I, CSI, TRI)) { - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.loadRegFromStackSlot(*MBB, I, Reg, CSI[i].getFrameIdx(), RC, TRI); - assert(I != MBB->begin() && - "loadRegFromStackSlot didn't insert any code!"); - // Insert in reverse order. loadRegFromStackSlot can insert - // multiple instructions. - if (AtStart) - I = MBB->begin(); - else { - I = BeforeI; - ++I; - } - } - } - } -} - -/// AdjustStackOffset - Helper function used to adjust the stack frame offset. -static inline void -AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx, - bool StackGrowsDown, int64_t &Offset, - unsigned &MaxAlign, unsigned Skew) { - // If the stack grows down, add the object size to find the lowest address. - if (StackGrowsDown) - Offset += MFI->getObjectSize(FrameIdx); - - unsigned Align = MFI->getObjectAlignment(FrameIdx); - - // If the alignment of this object is greater than that of the stack, then - // increase the stack alignment to match. - MaxAlign = std::max(MaxAlign, Align); - - // Adjust to alignment boundary. - Offset = RoundUpToAlignment(Offset, Align, Skew); - - if (StackGrowsDown) { - DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset << "]\n"); - MFI->setObjectOffset(FrameIdx, -Offset); // Set the computed offset - } else { - DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset << "]\n"); - MFI->setObjectOffset(FrameIdx, Offset); - Offset += MFI->getObjectSize(FrameIdx); - } -} - -/// AssignProtectedObjSet - Helper function to assign large stack objects (i.e., -/// those required to be close to the Stack Protector) to stack offsets. -static void -AssignProtectedObjSet(const StackObjSet &UnassignedObjs, - SmallSet<int, 16> &ProtectedObjs, - MachineFrameInfo *MFI, bool StackGrowsDown, - int64_t &Offset, unsigned &MaxAlign, unsigned Skew) { - - for (StackObjSet::const_iterator I = UnassignedObjs.begin(), - E = UnassignedObjs.end(); I != E; ++I) { - int i = *I; - AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign, Skew); - ProtectedObjs.insert(i); - } -} - -/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the -/// abstract stack objects. -/// -void WasmPEI::calculateFrameObjectOffsets(MachineFunction &Fn) { - const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); - StackProtector *SP = &getAnalysis<StackProtector>(); - - bool StackGrowsDown = - TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; - - // Loop over all of the stack objects, assigning sequential addresses... - MachineFrameInfo *MFI = Fn.getFrameInfo(); - - // Start at the beginning of the local area. - // The Offset is the distance from the stack top in the direction - // of stack growth -- so it's always nonnegative. - int LocalAreaOffset = TFI.getOffsetOfLocalArea(); - if (StackGrowsDown) - LocalAreaOffset = -LocalAreaOffset; - assert(LocalAreaOffset >= 0 - && "Local area offset should be in direction of stack growth"); - int64_t Offset = LocalAreaOffset; - - // Skew to be applied to alignment. - unsigned Skew = TFI.getStackAlignmentSkew(Fn); - - // If there are fixed sized objects that are preallocated in the local area, - // non-fixed objects can't be allocated right at the start of local area. - // We currently don't support filling in holes in between fixed sized - // objects, so we adjust 'Offset' to point to the end of last fixed sized - // preallocated object. - for (int i = MFI->getObjectIndexBegin(); i != 0; ++i) { - int64_t FixedOff; - if (StackGrowsDown) { - // The maximum distance from the stack pointer is at lower address of - // the object -- which is given by offset. For down growing stack - // the offset is negative, so we negate the offset to get the distance. - FixedOff = -MFI->getObjectOffset(i); - } else { - // The maximum distance from the start pointer is at the upper - // address of the object. - FixedOff = MFI->getObjectOffset(i) + MFI->getObjectSize(i); - } - if (FixedOff > Offset) Offset = FixedOff; - } - - // First assign frame offsets to stack objects that are used to spill - // callee saved registers. - if (StackGrowsDown) { - for (unsigned i = MinCSFrameIndex; i <= MaxCSFrameIndex; ++i) { - // If the stack grows down, we need to add the size to find the lowest - // address of the object. - Offset += MFI->getObjectSize(i); - - unsigned Align = MFI->getObjectAlignment(i); - // Adjust to alignment boundary - Offset = RoundUpToAlignment(Offset, Align, Skew); - - MFI->setObjectOffset(i, -Offset); // Set the computed offset - } - } else { - int MaxCSFI = MaxCSFrameIndex, MinCSFI = MinCSFrameIndex; - for (int i = MaxCSFI; i >= MinCSFI ; --i) { - unsigned Align = MFI->getObjectAlignment(i); - // Adjust to alignment boundary - Offset = RoundUpToAlignment(Offset, Align, Skew); - - MFI->setObjectOffset(i, Offset); - Offset += MFI->getObjectSize(i); - } - } - - unsigned MaxAlign = MFI->getMaxAlignment(); - - // Make sure the special register scavenging spill slot is closest to the - // incoming stack pointer if a frame pointer is required and is closer - // to the incoming rather than the final stack pointer. - const TargetRegisterInfo *RegInfo = Fn.getSubtarget().getRegisterInfo(); - bool EarlyScavengingSlots = (TFI.hasFP(Fn) && - TFI.isFPCloseToIncomingSP() && - RegInfo->useFPForScavengingIndex(Fn) && - !RegInfo->needsStackRealignment(Fn)); - if (RS && EarlyScavengingSlots) { - SmallVector<int, 2> SFIs; - RS->getScavengingFrameIndices(SFIs); - for (SmallVectorImpl<int>::iterator I = SFIs.begin(), - IE = SFIs.end(); I != IE; ++I) - AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign, Skew); - } - - // FIXME: Once this is working, then enable flag will change to a target - // check for whether the frame is large enough to want to use virtual - // frame index registers. Functions which don't want/need this optimization - // will continue to use the existing code path. - if (MFI->getUseLocalStackAllocationBlock()) { - unsigned Align = MFI->getLocalFrameMaxAlign(); - - // Adjust to alignment boundary. - Offset = RoundUpToAlignment(Offset, Align, Skew); - - DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n"); - - // Resolve offsets for objects in the local block. - for (unsigned i = 0, e = MFI->getLocalFrameObjectCount(); i != e; ++i) { - std::pair<int, int64_t> Entry = MFI->getLocalFrameObjectMap(i); - int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second; - DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << - FIOffset << "]\n"); - MFI->setObjectOffset(Entry.first, FIOffset); - } - // Allocate the local block - Offset += MFI->getLocalFrameSize(); - - MaxAlign = std::max(Align, MaxAlign); - } - - // Make sure that the stack protector comes before the local variables on the - // stack. - SmallSet<int, 16> ProtectedObjs; - if (MFI->getStackProtectorIndex() >= 0) { - StackObjSet LargeArrayObjs; - StackObjSet SmallArrayObjs; - StackObjSet AddrOfObjs; - - AdjustStackOffset(MFI, MFI->getStackProtectorIndex(), StackGrowsDown, - Offset, MaxAlign, Skew); - - // Assign large stack objects first. - for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { - if (MFI->isObjectPreAllocated(i) && - MFI->getUseLocalStackAllocationBlock()) - continue; - if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex) - continue; - if (RS && RS->isScavengingFrameIndex((int)i)) - continue; - if (MFI->isDeadObjectIndex(i)) - continue; - if (MFI->getStackProtectorIndex() == (int)i) - continue; - - switch (SP->getSSPLayout(MFI->getObjectAllocation(i))) { - case StackProtector::SSPLK_None: - continue; - case StackProtector::SSPLK_SmallArray: - SmallArrayObjs.insert(i); - continue; - case StackProtector::SSPLK_AddrOf: - AddrOfObjs.insert(i); - continue; - case StackProtector::SSPLK_LargeArray: - LargeArrayObjs.insert(i); - continue; - } - llvm_unreachable("Unexpected SSPLayoutKind."); - } - - AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown, - Offset, MaxAlign, Skew); - AssignProtectedObjSet(SmallArrayObjs, ProtectedObjs, MFI, StackGrowsDown, - Offset, MaxAlign, Skew); - AssignProtectedObjSet(AddrOfObjs, ProtectedObjs, MFI, StackGrowsDown, - Offset, MaxAlign, Skew); - } - - // Then assign frame offsets to stack objects that are not used to spill - // callee saved registers. - for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { - if (MFI->isObjectPreAllocated(i) && - MFI->getUseLocalStackAllocationBlock()) - continue; - if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex) - continue; - if (RS && RS->isScavengingFrameIndex((int)i)) - continue; - if (MFI->isDeadObjectIndex(i)) - continue; - if (MFI->getStackProtectorIndex() == (int)i) - continue; - if (ProtectedObjs.count(i)) - continue; - - AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign, Skew); - } - - // Make sure the special register scavenging spill slot is closest to the - // stack pointer. - if (RS && !EarlyScavengingSlots) { - SmallVector<int, 2> SFIs; - RS->getScavengingFrameIndices(SFIs); - for (SmallVectorImpl<int>::iterator I = SFIs.begin(), - IE = SFIs.end(); I != IE; ++I) - AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign, Skew); - } - - if (!TFI.targetHandlesStackFrameRounding()) { - // If we have reserved argument space for call sites in the function - // immediately on entry to the current function, count it as part of the - // overall stack size. - if (MFI->adjustsStack() && TFI.hasReservedCallFrame(Fn)) - Offset += MFI->getMaxCallFrameSize(); - - // Round up the size to a multiple of the alignment. If the function has - // any calls or alloca's, align to the target's StackAlignment value to - // ensure that the callee's frame or the alloca data is suitably aligned; - // otherwise, for leaf functions, align to the TransientStackAlignment - // value. - unsigned StackAlign; - if (MFI->adjustsStack() || MFI->hasVarSizedObjects() || - (RegInfo->needsStackRealignment(Fn) && MFI->getObjectIndexEnd() != 0)) - StackAlign = TFI.getStackAlignment(); - else - StackAlign = TFI.getTransientStackAlignment(); - - // If the frame pointer is eliminated, all frame offsets will be relative to - // SP not FP. Align to MaxAlign so this works. - StackAlign = std::max(StackAlign, MaxAlign); - Offset = RoundUpToAlignment(Offset, StackAlign, Skew); - } - - // Update frame info to pretend that this is part of the stack... - int64_t StackSize = Offset - LocalAreaOffset; - MFI->setStackSize(StackSize); - NumBytesStackSpace += StackSize; -} - -/// insertPrologEpilogCode - Scan the function for modified callee saved -/// registers, insert spill code for these callee saved registers, then add -/// prolog and epilog code to the function. -/// -void WasmPEI::insertPrologEpilogCode(MachineFunction &Fn) { - const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); - - // Add prologue to the function... - for (MachineBasicBlock *SaveBlock : SaveBlocks) - TFI.emitPrologue(Fn, *SaveBlock); - - // Add epilogue to restore the callee-save registers in each exiting block. - for (MachineBasicBlock *RestoreBlock : RestoreBlocks) - TFI.emitEpilogue(Fn, *RestoreBlock); - - for (MachineBasicBlock *SaveBlock : SaveBlocks) - TFI.inlineStackProbe(Fn, *SaveBlock); - - // Emit additional code that is required to support segmented stacks, if - // we've been asked for it. This, when linked with a runtime with support - // for segmented stacks (libgcc is one), will result in allocating stack - // space in small chunks instead of one large contiguous block. - if (Fn.shouldSplitStack()) { - for (MachineBasicBlock *SaveBlock : SaveBlocks) - TFI.adjustForSegmentedStacks(Fn, *SaveBlock); - } - - // Emit additional code that is required to explicitly handle the stack in - // HiPE native code (if needed) when loaded in the Erlang/OTP runtime. The - // approach is rather similar to that of Segmented Stacks, but it uses a - // different conditional check and another BIF for allocating more stack - // space. - if (Fn.getFunction()->getCallingConv() == CallingConv::HiPE) - for (MachineBasicBlock *SaveBlock : SaveBlocks) - TFI.adjustForHiPEPrologue(Fn, *SaveBlock); -} - -/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical -/// register references and actual offsets. -/// -void WasmPEI::replaceFrameIndices(MachineFunction &Fn) { - const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); - if (!TFI.needsFrameIndexResolution(Fn)) return; - - // Store SPAdj at exit of a basic block. - SmallVector<int, 8> SPState; - SPState.resize(Fn.getNumBlockIDs()); - SmallPtrSet<MachineBasicBlock*, 8> Reachable; - - // Iterate over the reachable blocks in DFS order. - for (auto DFI = df_ext_begin(&Fn, Reachable), DFE = df_ext_end(&Fn, Reachable); - DFI != DFE; ++DFI) { - int SPAdj = 0; - // Check the exit state of the DFS stack predecessor. - if (DFI.getPathLength() >= 2) { - MachineBasicBlock *StackPred = DFI.getPath(DFI.getPathLength() - 2); - assert(Reachable.count(StackPred) && - "DFS stack predecessor is already visited.\n"); - SPAdj = SPState[StackPred->getNumber()]; - } - MachineBasicBlock *BB = *DFI; - replaceFrameIndices(BB, Fn, SPAdj); - SPState[BB->getNumber()] = SPAdj; - } - - // Handle the unreachable blocks. - for (auto &BB : Fn) { - if (Reachable.count(&BB)) - // Already handled in DFS traversal. - continue; - int SPAdj = 0; - replaceFrameIndices(&BB, Fn, SPAdj); - } -} - -void WasmPEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn, - int &SPAdj) { - assert(Fn.getSubtarget().getRegisterInfo() && - "getRegisterInfo() must be implemented!"); - const TargetInstrInfo &TII = *Fn.getSubtarget().getInstrInfo(); - const TargetRegisterInfo &TRI = *Fn.getSubtarget().getRegisterInfo(); - const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); - unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode(); - unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode(); - - if (RS && !FrameIndexVirtualScavenging) RS->enterBasicBlock(BB); - - bool InsideCallSequence = false; - - for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) { - - if (I->getOpcode() == FrameSetupOpcode || - I->getOpcode() == FrameDestroyOpcode) { - InsideCallSequence = (I->getOpcode() == FrameSetupOpcode); - SPAdj += TII.getSPAdjust(I); - - MachineBasicBlock::iterator PrevI = BB->end(); - if (I != BB->begin()) PrevI = std::prev(I); - TFI->eliminateCallFramePseudoInstr(Fn, *BB, I); - - // Visit the instructions created by eliminateCallFramePseudoInstr(). - if (PrevI == BB->end()) - I = BB->begin(); // The replaced instr was the first in the block. - else - I = std::next(PrevI); - continue; - } - - MachineInstr *MI = I; - bool DoIncr = true; - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - if (!MI->getOperand(i).isFI()) - continue; - - // Frame indices in debug values are encoded in a target independent - // way with simply the frame index and offset rather than any - // target-specific addressing mode. - if (MI->isDebugValue()) { - assert(i == 0 && "Frame indices can only appear as the first " - "operand of a DBG_VALUE machine instruction"); - unsigned Reg; - MachineOperand &Offset = MI->getOperand(1); - Offset.setImm(Offset.getImm() + - TFI->getFrameIndexReference( - Fn, MI->getOperand(0).getIndex(), Reg)); - MI->getOperand(0).ChangeToRegister(Reg, false /*isDef*/); - continue; - } - - // TODO: This code should be commoned with the code for - // PATCHPOINT. There's no good reason for the difference in - // implementation other than historical accident. The only - // remaining difference is the unconditional use of the stack - // pointer as the base register. - if (MI->getOpcode() == TargetOpcode::STATEPOINT) { - assert((!MI->isDebugValue() || i == 0) && - "Frame indicies can only appear as the first operand of a " - "DBG_VALUE machine instruction"); - unsigned Reg; - MachineOperand &Offset = MI->getOperand(i + 1); - const unsigned refOffset = - TFI->getFrameIndexReferenceFromSP(Fn, MI->getOperand(i).getIndex(), - Reg); - - Offset.setImm(Offset.getImm() + refOffset); - MI->getOperand(i).ChangeToRegister(Reg, false /*isDef*/); - continue; - } - - // Some instructions (e.g. inline asm instructions) can have - // multiple frame indices and/or cause eliminateFrameIndex - // to insert more than one instruction. We need the register - // scavenger to go through all of these instructions so that - // it can update its register information. We keep the - // iterator at the point before insertion so that we can - // revisit them in full. - bool AtBeginning = (I == BB->begin()); - if (!AtBeginning) --I; - - // If this instruction has a FrameIndex operand, we need to - // use that target machine register info object to eliminate - // it. - TRI.eliminateFrameIndex(MI, SPAdj, i, - FrameIndexVirtualScavenging ? nullptr : RS); - - // Reset the iterator if we were at the beginning of the BB. - if (AtBeginning) { - I = BB->begin(); - DoIncr = false; - } - - MI = nullptr; - break; - } - - // If we are looking at a call sequence, we need to keep track of - // the SP adjustment made by each instruction in the sequence. - // This includes both the frame setup/destroy pseudos (handled above), - // as well as other instructions that have side effects w.r.t the SP. - // Note that this must come after eliminateFrameIndex, because - // if I itself referred to a frame index, we shouldn't count its own - // adjustment. - if (MI && InsideCallSequence) - SPAdj += TII.getSPAdjust(MI); - - if (DoIncr && I != BB->end()) ++I; - - // Update register states. - if (RS && !FrameIndexVirtualScavenging && MI) RS->forward(MI); - } -} - -/// scavengeFrameVirtualRegs - Replace all frame index virtual registers -/// with physical registers. Use the register scavenger to find an -/// appropriate register to use. -/// -/// FIXME: Iterating over the instruction stream is unnecessary. We can simply -/// iterate over the vreg use list, which at this point only contains machine -/// operands for which eliminateFrameIndex need a new scratch reg. -void -WasmPEI::scavengeFrameVirtualRegs(MachineFunction &Fn) { - // Run through the instructions and find any virtual registers. - for (MachineFunction::iterator BB = Fn.begin(), - E = Fn.end(); BB != E; ++BB) { - RS->enterBasicBlock(&*BB); - - int SPAdj = 0; - - // The instruction stream may change in the loop, so check BB->end() - // directly. - for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) { - // We might end up here again with a NULL iterator if we scavenged a - // register for which we inserted spill code for definition by what was - // originally the first instruction in BB. - if (I == MachineBasicBlock::iterator(nullptr)) - I = BB->begin(); - - MachineInstr *MI = I; - MachineBasicBlock::iterator J = std::next(I); - MachineBasicBlock::iterator P = - I == BB->begin() ? MachineBasicBlock::iterator(nullptr) - : std::prev(I); - - // RS should process this instruction before we might scavenge at this - // location. This is because we might be replacing a virtual register - // defined by this instruction, and if so, registers killed by this - // instruction are available, and defined registers are not. - RS->forward(I); - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - if (MI->getOperand(i).isReg()) { - MachineOperand &MO = MI->getOperand(i); - unsigned Reg = MO.getReg(); - if (Reg == 0) - continue; - if (!TargetRegisterInfo::isVirtualRegister(Reg)) - continue; - - // When we first encounter a new virtual register, it - // must be a definition. - assert(MI->getOperand(i).isDef() && - "frame index virtual missing def!"); - // Scavenge a new scratch register - const TargetRegisterClass *RC = Fn.getRegInfo().getRegClass(Reg); - unsigned ScratchReg = RS->scavengeRegister(RC, J, SPAdj); - - ++NumScavengedRegs; - - // Replace this reference to the virtual register with the - // scratch register. - assert (ScratchReg && "Missing scratch register!"); - Fn.getRegInfo().replaceRegWith(Reg, ScratchReg); - - // Because this instruction was processed by the RS before this - // register was allocated, make sure that the RS now records the - // register as being used. - RS->setRegUsed(ScratchReg); - } - } - - // If the scavenger needed to use one of its spill slots, the - // spill code will have been inserted in between I and J. This is a - // problem because we need the spill code before I: Move I to just - // prior to J. - if (I != std::prev(J)) { - BB->splice(J, &*BB, I); - - // Before we move I, we need to prepare the RS to visit I again. - // Specifically, RS will assert if it sees uses of registers that - // it believes are undefined. Because we have already processed - // register kills in I, when it visits I again, it will believe that - // those registers are undefined. To avoid this situation, unprocess - // the instruction I. - assert(RS->getCurrentPosition() == I && - "The register scavenger has an unexpected position"); - I = P; - RS->unprocess(P); - } else - ++I; - } - } -} diff --git a/gnu/llvm/lib/Target/X86/AsmParser/Makefile b/gnu/llvm/lib/Target/X86/AsmParser/Makefile deleted file mode 100644 index f834dfc300a..00000000000 --- a/gnu/llvm/lib/Target/X86/AsmParser/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/X86/AsmParser/Makefile -------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMX86AsmParser - -# Hack: we need to include 'main' X86 target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/X86/Disassembler/Makefile b/gnu/llvm/lib/Target/X86/Disassembler/Makefile deleted file mode 100644 index 51e7b828cf2..00000000000 --- a/gnu/llvm/lib/Target/X86/Disassembler/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -##===- lib/Target/X86/Disassembler/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMX86Disassembler - -# Hack: we need to include 'main' x86 target directory to grab private headers. -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common - -.PHONY: $(PROJ_SRC_DIR)/X86DisassemblerDecoder.c diff --git a/gnu/llvm/lib/Target/X86/Disassembler/X86Disassembler.h b/gnu/llvm/lib/Target/X86/Disassembler/X86Disassembler.h deleted file mode 100644 index d7f426b2641..00000000000 --- a/gnu/llvm/lib/Target/X86/Disassembler/X86Disassembler.h +++ /dev/null @@ -1,112 +0,0 @@ -//===-- X86Disassembler.h - Disassembler for x86 and x86_64 -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The X86 disassembler is a table-driven disassembler for the 16-, 32-, and -// 64-bit X86 instruction sets. The main decode sequence for an assembly -// instruction in this disassembler is: -// -// 1. Read the prefix bytes and determine the attributes of the instruction. -// These attributes, recorded in enum attributeBits -// (X86DisassemblerDecoderCommon.h), form a bitmask. The table CONTEXTS_SYM -// provides a mapping from bitmasks to contexts, which are represented by -// enum InstructionContext (ibid.). -// -// 2. Read the opcode, and determine what kind of opcode it is. The -// disassembler distinguishes four kinds of opcodes, which are enumerated in -// OpcodeType (X86DisassemblerDecoderCommon.h): one-byte (0xnn), two-byte -// (0x0f 0xnn), three-byte-38 (0x0f 0x38 0xnn), or three-byte-3a -// (0x0f 0x3a 0xnn). Mandatory prefixes are treated as part of the context. -// -// 3. Depending on the opcode type, look in one of four ClassDecision structures -// (X86DisassemblerDecoderCommon.h). Use the opcode class to determine which -// OpcodeDecision (ibid.) to look the opcode in. Look up the opcode, to get -// a ModRMDecision (ibid.). -// -// 4. Some instructions, such as escape opcodes or extended opcodes, or even -// instructions that have ModRM*Reg / ModRM*Mem forms in LLVM, need the -// ModR/M byte to complete decode. The ModRMDecision's type is an entry from -// ModRMDecisionType (X86DisassemblerDecoderCommon.h) that indicates if the -// ModR/M byte is required and how to interpret it. -// -// 5. After resolving the ModRMDecision, the disassembler has a unique ID -// of type InstrUID (X86DisassemblerDecoderCommon.h). Looking this ID up in -// INSTRUCTIONS_SYM yields the name of the instruction and the encodings and -// meanings of its operands. -// -// 6. For each operand, its encoding is an entry from OperandEncoding -// (X86DisassemblerDecoderCommon.h) and its type is an entry from -// OperandType (ibid.). The encoding indicates how to read it from the -// instruction; the type indicates how to interpret the value once it has -// been read. For example, a register operand could be stored in the R/M -// field of the ModR/M byte, the REG field of the ModR/M byte, or added to -// the main opcode. This is orthogonal from its meaning (an GPR or an XMM -// register, for instance). Given this information, the operands can be -// extracted and interpreted. -// -// 7. As the last step, the disassembler translates the instruction information -// and operands into a format understandable by the client - in this case, an -// MCInst for use by the MC infrastructure. -// -// The disassembler is broken broadly into two parts: the table emitter that -// emits the instruction decode tables discussed above during compilation, and -// the disassembler itself. The table emitter is documented in more detail in -// utils/TableGen/X86DisassemblerEmitter.h. -// -// X86Disassembler.h contains the public interface for the disassembler, -// adhering to the MCDisassembler interface. -// X86Disassembler.cpp contains the code responsible for step 7, and for -// invoking the decoder to execute steps 1-6. -// X86DisassemblerDecoderCommon.h contains the definitions needed by both the -// table emitter and the disassembler. -// X86DisassemblerDecoder.h contains the public interface of the decoder, -// factored out into C for possible use by other projects. -// X86DisassemblerDecoder.c contains the source code of the decoder, which is -// responsible for steps 1-6. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_X86_DISASSEMBLER_X86DISASSEMBLER_H -#define LLVM_LIB_TARGET_X86_DISASSEMBLER_X86DISASSEMBLER_H - -#include "X86DisassemblerDecoderCommon.h" -#include "llvm/MC/MCDisassembler.h" - -namespace llvm { - -class MCInst; -class MCInstrInfo; -class MCSubtargetInfo; -class MemoryObject; -class raw_ostream; - -namespace X86Disassembler { - -/// Generic disassembler for all X86 platforms. All each platform class should -/// have to do is subclass the constructor, and provide a different -/// disassemblerMode value. -class X86GenericDisassembler : public MCDisassembler { - std::unique_ptr<const MCInstrInfo> MII; -public: - X86GenericDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, - std::unique_ptr<const MCInstrInfo> MII); -public: - DecodeStatus getInstruction(MCInst &instr, uint64_t &size, - ArrayRef<uint8_t> Bytes, uint64_t Address, - raw_ostream &vStream, - raw_ostream &cStream) const override; - -private: - DisassemblerMode fMode; -}; - -} // namespace X86Disassembler - -} // namespace llvm - -#endif diff --git a/gnu/llvm/lib/Target/X86/InstPrinter/Makefile b/gnu/llvm/lib/Target/X86/InstPrinter/Makefile deleted file mode 100644 index c82aa330a20..00000000000 --- a/gnu/llvm/lib/Target/X86/InstPrinter/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/X86/AsmPrinter/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMX86AsmPrinter - -# Hack: we need to include 'main' x86 target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/X86/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/X86/MCTargetDesc/Makefile deleted file mode 100644 index b19774ee379..00000000000 --- a/gnu/llvm/lib/Target/X86/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/X86/TargetDesc/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMX86Desc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp b/gnu/llvm/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp deleted file mode 100644 index ddb764facdb..00000000000 --- a/gnu/llvm/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp +++ /dev/null @@ -1,141 +0,0 @@ -//===-- X86ELFRelocationInfo.cpp ----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/X86MCTargetDesc.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCRelocationInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Object/ELFObjectFile.h" -#include "llvm/Support/ELF.h" - -using namespace llvm; -using namespace object; -using namespace ELF; - -namespace { -class X86_64ELFRelocationInfo : public MCRelocationInfo { -public: - X86_64ELFRelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {} - - const MCExpr *createExprForRelocation(RelocationRef Rel) override { - uint64_t RelType = Rel.getType(); - elf_symbol_iterator SymI = Rel.getSymbol(); - - ErrorOr<StringRef> SymNameOrErr = SymI->getName(); - if (std::error_code EC = SymNameOrErr.getError()) - report_fatal_error(EC.message()); - StringRef SymName = *SymNameOrErr; - - ErrorOr<uint64_t> SymAddr = SymI->getAddress(); - if (std::error_code EC = SymAddr.getError()) - report_fatal_error(EC.message()); - uint64_t SymSize = SymI->getSize(); - int64_t Addend = *ELFRelocationRef(Rel).getAddend(); - - MCSymbol *Sym = Ctx.getOrCreateSymbol(SymName); - // FIXME: check that the value is actually the same. - if (!Sym->isVariable()) - Sym->setVariableValue(MCConstantExpr::create(*SymAddr, Ctx)); - - const MCExpr *Expr = nullptr; - // If hasAddend is true, then we need to add Addend (r_addend) to Expr. - bool hasAddend = false; - - // The AMD64 SysV ABI says: - // A: the addend used to compute the value of the relocatable field. - // B: the base address at which a shared object has been loaded into memory - // during execution. Generally, a shared object is built with a 0 base - // virtual address, but the execution address will be different. - // G: the offset into the global offset table at which the relocation - // entry's symbol will reside during execution. - // GOT: the address of the global offset table. - // L: the place (section offset or address) of the Procedure Linkage Table - // entry for a symbol. - // P: the place (section offset or address) of the storage unit being - // relocated (computed using r_offset). - // S: the value of the symbol whose index resides in the relocation entry. - // Z: the size of the symbol whose index resides in the relocation entry. - - switch(RelType) { - case R_X86_64_NONE: - case R_X86_64_COPY: - // none - break; - case R_X86_64_64: - case R_X86_64_16: - case R_X86_64_8: - // S + A - case R_X86_64_32: - case R_X86_64_32S: - // S + A (We don't care about the result not fitting in 32 bits.) - case R_X86_64_PC32: - case R_X86_64_PC16: - case R_X86_64_PC8: - case R_X86_64_PC64: - // S + A - P (P/pcrel is implicit) - hasAddend = true; - Expr = MCSymbolRefExpr::create(Sym, Ctx); - break; - case R_X86_64_GOT32: - case R_X86_64_GOT64: - case R_X86_64_GOTPC32: - case R_X86_64_GOTPC64: - case R_X86_64_GOTPLT64: - // G + A - hasAddend = true; - Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, Ctx); - break; - case R_X86_64_PLT32: - // L + A - P -> S@PLT + A - hasAddend = true; - Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_PLT, Ctx); - break; - case R_X86_64_GLOB_DAT: - case R_X86_64_JUMP_SLOT: - // S - Expr = MCSymbolRefExpr::create(Sym, Ctx); - break; - case R_X86_64_GOTPCREL: - case R_X86_64_GOTPCREL64: - // G + GOT + A - P -> S@GOTPCREL + A - hasAddend = true; - Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx); - break; - case R_X86_64_GOTOFF64: - // S + A - GOT - Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTOFF, Ctx); - break; - case R_X86_64_PLTOFF64: - // L + A - GOT - break; - case R_X86_64_SIZE32: - case R_X86_64_SIZE64: - // Z + A - Expr = MCConstantExpr::create(SymSize, Ctx); - break; - default: - Expr = MCSymbolRefExpr::create(Sym, Ctx); - break; - } - if (Expr && hasAddend && Addend != 0) - Expr = MCBinaryExpr::createAdd(Expr, - MCConstantExpr::create(Addend, Ctx), - Ctx); - return Expr; - } -}; -} // End unnamed namespace - -/// createX86ELFRelocationInfo - Construct an X86 Mach-O RelocationInfo. -MCRelocationInfo *llvm::createX86_64ELFRelocationInfo(MCContext &Ctx) { - // We only handle x86-64 for now. - return new X86_64ELFRelocationInfo(Ctx); -} diff --git a/gnu/llvm/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp b/gnu/llvm/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp deleted file mode 100644 index 9bfe999424f..00000000000 --- a/gnu/llvm/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp +++ /dev/null @@ -1,119 +0,0 @@ -//===-- X86MachORelocationInfo.cpp ----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/X86MCTargetDesc.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCRelocationInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Object/MachO.h" - -using namespace llvm; -using namespace object; -using namespace MachO; - -namespace { -class X86_64MachORelocationInfo : public MCRelocationInfo { -public: - X86_64MachORelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {} - - const MCExpr *createExprForRelocation(RelocationRef Rel) override { - const MachOObjectFile *Obj = cast<MachOObjectFile>(Rel.getObject()); - - uint64_t RelType = Rel.getType(); - symbol_iterator SymI = Rel.getSymbol(); - - ErrorOr<StringRef> SymNameOrErr = SymI->getName(); - if (std::error_code EC = SymNameOrErr.getError()) - report_fatal_error(EC.message()); - StringRef SymName = *SymNameOrErr; - uint64_t SymAddr = SymI->getValue(); - - any_relocation_info RE = Obj->getRelocation(Rel.getRawDataRefImpl()); - bool isPCRel = Obj->getAnyRelocationPCRel(RE); - - MCSymbol *Sym = Ctx.getOrCreateSymbol(SymName); - // FIXME: check that the value is actually the same. - if (!Sym->isVariable()) - Sym->setVariableValue(MCConstantExpr::create(SymAddr, Ctx)); - const MCExpr *Expr = nullptr; - - switch(RelType) { - case X86_64_RELOC_TLV: - Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_TLVP, Ctx); - break; - case X86_64_RELOC_SIGNED_4: - Expr = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Sym, Ctx), - MCConstantExpr::create(4, Ctx), - Ctx); - break; - case X86_64_RELOC_SIGNED_2: - Expr = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Sym, Ctx), - MCConstantExpr::create(2, Ctx), - Ctx); - break; - case X86_64_RELOC_SIGNED_1: - Expr = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Sym, Ctx), - MCConstantExpr::create(1, Ctx), - Ctx); - break; - case X86_64_RELOC_GOT_LOAD: - Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx); - break; - case X86_64_RELOC_GOT: - Expr = MCSymbolRefExpr::create(Sym, isPCRel ? - MCSymbolRefExpr::VK_GOTPCREL : - MCSymbolRefExpr::VK_GOT, - Ctx); - break; - case X86_64_RELOC_SUBTRACTOR: - { - Rel.moveNext(); - any_relocation_info RENext = - Obj->getRelocation(Rel.getRawDataRefImpl()); - - // X86_64_SUBTRACTOR must be followed by a relocation of type - // X86_64_RELOC_UNSIGNED. - // NOTE: Scattered relocations don't exist on x86_64. - unsigned RType = Obj->getAnyRelocationType(RENext); - if (RType != X86_64_RELOC_UNSIGNED) - report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " - "X86_64_RELOC_SUBTRACTOR."); - - const MCExpr *LHS = MCSymbolRefExpr::create(Sym, Ctx); - - symbol_iterator RSymI = Rel.getSymbol(); - uint64_t RSymAddr = RSymI->getValue(); - ErrorOr<StringRef> RSymName = RSymI->getName(); - if (std::error_code EC = RSymName.getError()) - report_fatal_error(EC.message()); - - MCSymbol *RSym = Ctx.getOrCreateSymbol(*RSymName); - if (!RSym->isVariable()) - RSym->setVariableValue(MCConstantExpr::create(RSymAddr, Ctx)); - - const MCExpr *RHS = MCSymbolRefExpr::create(RSym, Ctx); - - Expr = MCBinaryExpr::createSub(LHS, RHS, Ctx); - break; - } - default: - Expr = MCSymbolRefExpr::create(Sym, Ctx); - break; - } - return Expr; - } -}; -} // End unnamed namespace - -/// createX86_64MachORelocationInfo - Construct an X86-64 Mach-O RelocationInfo. -MCRelocationInfo *llvm::createX86_64MachORelocationInfo(MCContext &Ctx) { - return new X86_64MachORelocationInfo(Ctx); -} diff --git a/gnu/llvm/lib/Target/X86/Makefile b/gnu/llvm/lib/Target/X86/Makefile deleted file mode 100644 index e518fecf044..00000000000 --- a/gnu/llvm/lib/Target/X86/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -##===- lib/Target/X86/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMX86CodeGen -TARGET = X86 - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = X86GenRegisterInfo.inc X86GenInstrInfo.inc \ - X86GenAsmWriter.inc X86GenAsmMatcher.inc \ - X86GenAsmWriter1.inc X86GenDAGISel.inc \ - X86GenDisassemblerTables.inc X86GenFastISel.inc \ - X86GenCallingConv.inc X86GenSubtargetInfo.inc - -DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc Utils - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/X86/TargetInfo/Makefile b/gnu/llvm/lib/Target/X86/TargetInfo/Makefile deleted file mode 100644 index ee91982df0c..00000000000 --- a/gnu/llvm/lib/Target/X86/TargetInfo/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/X86/TargetInfo/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMX86Info - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/X86/Utils/Makefile b/gnu/llvm/lib/Target/X86/Utils/Makefile deleted file mode 100644 index 1df6f0f561d..00000000000 --- a/gnu/llvm/lib/Target/X86/Utils/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/X86/Utils/Makefile -----------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMX86Utils - -# Hack: we need to include 'main' x86 target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/XCore/Disassembler/Makefile b/gnu/llvm/lib/Target/XCore/Disassembler/Makefile deleted file mode 100644 index 4caffdd1da6..00000000000 --- a/gnu/llvm/lib/Target/XCore/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/XCore/Disassembler/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMXCoreDisassembler - -# Hack: we need to include 'main' XCore target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/XCore/InstPrinter/Makefile b/gnu/llvm/lib/Target/XCore/InstPrinter/Makefile deleted file mode 100644 index 1c1c61299c3..00000000000 --- a/gnu/llvm/lib/Target/XCore/InstPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/XCore/AsmPrinter/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMXCoreAsmPrinter - -# Hack: we need to include 'main' xcore target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/XCore/MCTargetDesc/Makefile b/gnu/llvm/lib/Target/XCore/MCTargetDesc/Makefile deleted file mode 100644 index de61543bfe9..00000000000 --- a/gnu/llvm/lib/Target/XCore/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/XCore/TargetDesc/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMXCoreDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Target/XCore/Makefile b/gnu/llvm/lib/Target/XCore/Makefile deleted file mode 100644 index 92ddc886087..00000000000 --- a/gnu/llvm/lib/Target/XCore/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -##===- lib/Target/XCore/Makefile ---------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMXCoreCodeGen -TARGET = XCore - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = XCoreGenRegisterInfo.inc XCoreGenInstrInfo.inc \ - XCoreGenAsmWriter.inc \ - XCoreGenDAGISel.inc XCoreGenCallingConv.inc \ - XCoreGenDisassemblerTables.inc XCoreGenSubtargetInfo.inc - -DIRS = Disassembler InstPrinter TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Target/XCore/TargetInfo/Makefile b/gnu/llvm/lib/Target/XCore/TargetInfo/Makefile deleted file mode 100644 index f8a40951749..00000000000 --- a/gnu/llvm/lib/Target/XCore/TargetInfo/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/XCore/TargetInfo/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMXCoreInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Transforms/Hello/Makefile b/gnu/llvm/lib/Transforms/Hello/Makefile deleted file mode 100644 index f1e31489d3c..00000000000 --- a/gnu/llvm/lib/Transforms/Hello/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -##===- lib/Transforms/Hello/Makefile -----------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMHello -LOADABLE_MODULE = 1 -USEDLIBS = - -# If we don't need RTTI or EH, there's no reason to export anything -# from the hello plugin. -ifneq ($(REQUIRES_RTTI), 1) -ifneq ($(REQUIRES_EH), 1) -EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/Hello.exports -endif -endif - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Transforms/IPO/LowerBitSets.cpp b/gnu/llvm/lib/Transforms/IPO/LowerBitSets.cpp deleted file mode 100644 index 7b515745c31..00000000000 --- a/gnu/llvm/lib/Transforms/IPO/LowerBitSets.cpp +++ /dev/null @@ -1,1055 +0,0 @@ -//===-- LowerBitSets.cpp - Bitset lowering pass ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass lowers bitset metadata and calls to the llvm.bitset.test intrinsic. -// See http://llvm.org/docs/LangRef.html#bitsets for more information. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/IPO/LowerBitSets.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/ADT/EquivalenceClasses.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/Triple.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalObject.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Operator.h" -#include "llvm/Pass.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" - -using namespace llvm; - -#define DEBUG_TYPE "lowerbitsets" - -STATISTIC(ByteArraySizeBits, "Byte array size in bits"); -STATISTIC(ByteArraySizeBytes, "Byte array size in bytes"); -STATISTIC(NumByteArraysCreated, "Number of byte arrays created"); -STATISTIC(NumBitSetCallsLowered, "Number of bitset calls lowered"); -STATISTIC(NumBitSetDisjointSets, "Number of disjoint sets of bitsets"); - -static cl::opt<bool> AvoidReuse( - "lowerbitsets-avoid-reuse", - cl::desc("Try to avoid reuse of byte array addresses using aliases"), - cl::Hidden, cl::init(true)); - -bool BitSetInfo::containsGlobalOffset(uint64_t Offset) const { - if (Offset < ByteOffset) - return false; - - if ((Offset - ByteOffset) % (uint64_t(1) << AlignLog2) != 0) - return false; - - uint64_t BitOffset = (Offset - ByteOffset) >> AlignLog2; - if (BitOffset >= BitSize) - return false; - - return Bits.count(BitOffset); -} - -bool BitSetInfo::containsValue( - const DataLayout &DL, - const DenseMap<GlobalObject *, uint64_t> &GlobalLayout, Value *V, - uint64_t COffset) const { - if (auto GV = dyn_cast<GlobalObject>(V)) { - auto I = GlobalLayout.find(GV); - if (I == GlobalLayout.end()) - return false; - return containsGlobalOffset(I->second + COffset); - } - - if (auto GEP = dyn_cast<GEPOperator>(V)) { - APInt APOffset(DL.getPointerSizeInBits(0), 0); - bool Result = GEP->accumulateConstantOffset(DL, APOffset); - if (!Result) - return false; - COffset += APOffset.getZExtValue(); - return containsValue(DL, GlobalLayout, GEP->getPointerOperand(), - COffset); - } - - if (auto Op = dyn_cast<Operator>(V)) { - if (Op->getOpcode() == Instruction::BitCast) - return containsValue(DL, GlobalLayout, Op->getOperand(0), COffset); - - if (Op->getOpcode() == Instruction::Select) - return containsValue(DL, GlobalLayout, Op->getOperand(1), COffset) && - containsValue(DL, GlobalLayout, Op->getOperand(2), COffset); - } - - return false; -} - -void BitSetInfo::print(raw_ostream &OS) const { - OS << "offset " << ByteOffset << " size " << BitSize << " align " - << (1 << AlignLog2); - - if (isAllOnes()) { - OS << " all-ones\n"; - return; - } - - OS << " { "; - for (uint64_t B : Bits) - OS << B << ' '; - OS << "}\n"; -} - -BitSetInfo BitSetBuilder::build() { - if (Min > Max) - Min = 0; - - // Normalize each offset against the minimum observed offset, and compute - // the bitwise OR of each of the offsets. The number of trailing zeros - // in the mask gives us the log2 of the alignment of all offsets, which - // allows us to compress the bitset by only storing one bit per aligned - // address. - uint64_t Mask = 0; - for (uint64_t &Offset : Offsets) { - Offset -= Min; - Mask |= Offset; - } - - BitSetInfo BSI; - BSI.ByteOffset = Min; - - BSI.AlignLog2 = 0; - if (Mask != 0) - BSI.AlignLog2 = countTrailingZeros(Mask, ZB_Undefined); - - // Build the compressed bitset while normalizing the offsets against the - // computed alignment. - BSI.BitSize = ((Max - Min) >> BSI.AlignLog2) + 1; - for (uint64_t Offset : Offsets) { - Offset >>= BSI.AlignLog2; - BSI.Bits.insert(Offset); - } - - return BSI; -} - -void GlobalLayoutBuilder::addFragment(const std::set<uint64_t> &F) { - // Create a new fragment to hold the layout for F. - Fragments.emplace_back(); - std::vector<uint64_t> &Fragment = Fragments.back(); - uint64_t FragmentIndex = Fragments.size() - 1; - - for (auto ObjIndex : F) { - uint64_t OldFragmentIndex = FragmentMap[ObjIndex]; - if (OldFragmentIndex == 0) { - // We haven't seen this object index before, so just add it to the current - // fragment. - Fragment.push_back(ObjIndex); - } else { - // This index belongs to an existing fragment. Copy the elements of the - // old fragment into this one and clear the old fragment. We don't update - // the fragment map just yet, this ensures that any further references to - // indices from the old fragment in this fragment do not insert any more - // indices. - std::vector<uint64_t> &OldFragment = Fragments[OldFragmentIndex]; - Fragment.insert(Fragment.end(), OldFragment.begin(), OldFragment.end()); - OldFragment.clear(); - } - } - - // Update the fragment map to point our object indices to this fragment. - for (uint64_t ObjIndex : Fragment) - FragmentMap[ObjIndex] = FragmentIndex; -} - -void ByteArrayBuilder::allocate(const std::set<uint64_t> &Bits, - uint64_t BitSize, uint64_t &AllocByteOffset, - uint8_t &AllocMask) { - // Find the smallest current allocation. - unsigned Bit = 0; - for (unsigned I = 1; I != BitsPerByte; ++I) - if (BitAllocs[I] < BitAllocs[Bit]) - Bit = I; - - AllocByteOffset = BitAllocs[Bit]; - - // Add our size to it. - unsigned ReqSize = AllocByteOffset + BitSize; - BitAllocs[Bit] = ReqSize; - if (Bytes.size() < ReqSize) - Bytes.resize(ReqSize); - - // Set our bits. - AllocMask = 1 << Bit; - for (uint64_t B : Bits) - Bytes[AllocByteOffset + B] |= AllocMask; -} - -namespace { - -struct ByteArrayInfo { - std::set<uint64_t> Bits; - uint64_t BitSize; - GlobalVariable *ByteArray; - Constant *Mask; -}; - -struct LowerBitSets : public ModulePass { - static char ID; - LowerBitSets() : ModulePass(ID) { - initializeLowerBitSetsPass(*PassRegistry::getPassRegistry()); - } - - Module *M; - - bool LinkerSubsectionsViaSymbols; - Triple::ArchType Arch; - Triple::ObjectFormatType ObjectFormat; - IntegerType *Int1Ty; - IntegerType *Int8Ty; - IntegerType *Int32Ty; - Type *Int32PtrTy; - IntegerType *Int64Ty; - IntegerType *IntPtrTy; - - // The llvm.bitsets named metadata. - NamedMDNode *BitSetNM; - - // Mapping from bitset identifiers to the call sites that test them. - DenseMap<Metadata *, std::vector<CallInst *>> BitSetTestCallSites; - - std::vector<ByteArrayInfo> ByteArrayInfos; - - BitSetInfo - buildBitSet(Metadata *BitSet, - const DenseMap<GlobalObject *, uint64_t> &GlobalLayout); - ByteArrayInfo *createByteArray(BitSetInfo &BSI); - void allocateByteArrays(); - Value *createBitSetTest(IRBuilder<> &B, BitSetInfo &BSI, ByteArrayInfo *&BAI, - Value *BitOffset); - void lowerBitSetCalls(ArrayRef<Metadata *> BitSets, - Constant *CombinedGlobalAddr, - const DenseMap<GlobalObject *, uint64_t> &GlobalLayout); - Value * - lowerBitSetCall(CallInst *CI, BitSetInfo &BSI, ByteArrayInfo *&BAI, - Constant *CombinedGlobal, - const DenseMap<GlobalObject *, uint64_t> &GlobalLayout); - void buildBitSetsFromGlobalVariables(ArrayRef<Metadata *> BitSets, - ArrayRef<GlobalVariable *> Globals); - unsigned getJumpTableEntrySize(); - Type *getJumpTableEntryType(); - Constant *createJumpTableEntry(GlobalObject *Src, Function *Dest, - unsigned Distance); - void verifyBitSetMDNode(MDNode *Op); - void buildBitSetsFromFunctions(ArrayRef<Metadata *> BitSets, - ArrayRef<Function *> Functions); - void buildBitSetsFromDisjointSet(ArrayRef<Metadata *> BitSets, - ArrayRef<GlobalObject *> Globals); - bool buildBitSets(); - bool eraseBitSetMetadata(); - - bool doInitialization(Module &M) override; - bool runOnModule(Module &M) override; -}; - -} // anonymous namespace - -INITIALIZE_PASS_BEGIN(LowerBitSets, "lowerbitsets", - "Lower bitset metadata", false, false) -INITIALIZE_PASS_END(LowerBitSets, "lowerbitsets", - "Lower bitset metadata", false, false) -char LowerBitSets::ID = 0; - -ModulePass *llvm::createLowerBitSetsPass() { return new LowerBitSets; } - -bool LowerBitSets::doInitialization(Module &Mod) { - M = &Mod; - const DataLayout &DL = Mod.getDataLayout(); - - Triple TargetTriple(M->getTargetTriple()); - LinkerSubsectionsViaSymbols = TargetTriple.isMacOSX(); - Arch = TargetTriple.getArch(); - ObjectFormat = TargetTriple.getObjectFormat(); - - Int1Ty = Type::getInt1Ty(M->getContext()); - Int8Ty = Type::getInt8Ty(M->getContext()); - Int32Ty = Type::getInt32Ty(M->getContext()); - Int32PtrTy = PointerType::getUnqual(Int32Ty); - Int64Ty = Type::getInt64Ty(M->getContext()); - IntPtrTy = DL.getIntPtrType(M->getContext(), 0); - - BitSetNM = M->getNamedMetadata("llvm.bitsets"); - - BitSetTestCallSites.clear(); - - return false; -} - -/// Build a bit set for BitSet using the object layouts in -/// GlobalLayout. -BitSetInfo LowerBitSets::buildBitSet( - Metadata *BitSet, - const DenseMap<GlobalObject *, uint64_t> &GlobalLayout) { - BitSetBuilder BSB; - - // Compute the byte offset of each element of this bitset. - if (BitSetNM) { - for (MDNode *Op : BitSetNM->operands()) { - if (Op->getOperand(0) != BitSet || !Op->getOperand(1)) - continue; - Constant *OpConst = - cast<ConstantAsMetadata>(Op->getOperand(1))->getValue(); - if (auto GA = dyn_cast<GlobalAlias>(OpConst)) - OpConst = GA->getAliasee(); - auto OpGlobal = dyn_cast<GlobalObject>(OpConst); - if (!OpGlobal) - continue; - uint64_t Offset = - cast<ConstantInt>(cast<ConstantAsMetadata>(Op->getOperand(2)) - ->getValue())->getZExtValue(); - - Offset += GlobalLayout.find(OpGlobal)->second; - - BSB.addOffset(Offset); - } - } - - return BSB.build(); -} - -/// Build a test that bit BitOffset mod sizeof(Bits)*8 is set in -/// Bits. This pattern matches to the bt instruction on x86. -static Value *createMaskedBitTest(IRBuilder<> &B, Value *Bits, - Value *BitOffset) { - auto BitsType = cast<IntegerType>(Bits->getType()); - unsigned BitWidth = BitsType->getBitWidth(); - - BitOffset = B.CreateZExtOrTrunc(BitOffset, BitsType); - Value *BitIndex = - B.CreateAnd(BitOffset, ConstantInt::get(BitsType, BitWidth - 1)); - Value *BitMask = B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex); - Value *MaskedBits = B.CreateAnd(Bits, BitMask); - return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0)); -} - -ByteArrayInfo *LowerBitSets::createByteArray(BitSetInfo &BSI) { - // Create globals to stand in for byte arrays and masks. These never actually - // get initialized, we RAUW and erase them later in allocateByteArrays() once - // we know the offset and mask to use. - auto ByteArrayGlobal = new GlobalVariable( - *M, Int8Ty, /*isConstant=*/true, GlobalValue::PrivateLinkage, nullptr); - auto MaskGlobal = new GlobalVariable( - *M, Int8Ty, /*isConstant=*/true, GlobalValue::PrivateLinkage, nullptr); - - ByteArrayInfos.emplace_back(); - ByteArrayInfo *BAI = &ByteArrayInfos.back(); - - BAI->Bits = BSI.Bits; - BAI->BitSize = BSI.BitSize; - BAI->ByteArray = ByteArrayGlobal; - BAI->Mask = ConstantExpr::getPtrToInt(MaskGlobal, Int8Ty); - return BAI; -} - -void LowerBitSets::allocateByteArrays() { - std::stable_sort(ByteArrayInfos.begin(), ByteArrayInfos.end(), - [](const ByteArrayInfo &BAI1, const ByteArrayInfo &BAI2) { - return BAI1.BitSize > BAI2.BitSize; - }); - - std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size()); - - ByteArrayBuilder BAB; - for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) { - ByteArrayInfo *BAI = &ByteArrayInfos[I]; - - uint8_t Mask; - BAB.allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[I], Mask); - - BAI->Mask->replaceAllUsesWith(ConstantInt::get(Int8Ty, Mask)); - cast<GlobalVariable>(BAI->Mask->getOperand(0))->eraseFromParent(); - } - - Constant *ByteArrayConst = ConstantDataArray::get(M->getContext(), BAB.Bytes); - auto ByteArray = - new GlobalVariable(*M, ByteArrayConst->getType(), /*isConstant=*/true, - GlobalValue::PrivateLinkage, ByteArrayConst); - - for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) { - ByteArrayInfo *BAI = &ByteArrayInfos[I]; - - Constant *Idxs[] = {ConstantInt::get(IntPtrTy, 0), - ConstantInt::get(IntPtrTy, ByteArrayOffsets[I])}; - Constant *GEP = ConstantExpr::getInBoundsGetElementPtr( - ByteArrayConst->getType(), ByteArray, Idxs); - - // Create an alias instead of RAUW'ing the gep directly. On x86 this ensures - // that the pc-relative displacement is folded into the lea instead of the - // test instruction getting another displacement. - if (LinkerSubsectionsViaSymbols) { - BAI->ByteArray->replaceAllUsesWith(GEP); - } else { - GlobalAlias *Alias = GlobalAlias::create( - Int8Ty, 0, GlobalValue::PrivateLinkage, "bits", GEP, M); - BAI->ByteArray->replaceAllUsesWith(Alias); - } - BAI->ByteArray->eraseFromParent(); - } - - ByteArraySizeBits = BAB.BitAllocs[0] + BAB.BitAllocs[1] + BAB.BitAllocs[2] + - BAB.BitAllocs[3] + BAB.BitAllocs[4] + BAB.BitAllocs[5] + - BAB.BitAllocs[6] + BAB.BitAllocs[7]; - ByteArraySizeBytes = BAB.Bytes.size(); -} - -/// Build a test that bit BitOffset is set in BSI, where -/// BitSetGlobal is a global containing the bits in BSI. -Value *LowerBitSets::createBitSetTest(IRBuilder<> &B, BitSetInfo &BSI, - ByteArrayInfo *&BAI, Value *BitOffset) { - if (BSI.BitSize <= 64) { - // If the bit set is sufficiently small, we can avoid a load by bit testing - // a constant. - IntegerType *BitsTy; - if (BSI.BitSize <= 32) - BitsTy = Int32Ty; - else - BitsTy = Int64Ty; - - uint64_t Bits = 0; - for (auto Bit : BSI.Bits) - Bits |= uint64_t(1) << Bit; - Constant *BitsConst = ConstantInt::get(BitsTy, Bits); - return createMaskedBitTest(B, BitsConst, BitOffset); - } else { - if (!BAI) { - ++NumByteArraysCreated; - BAI = createByteArray(BSI); - } - - Constant *ByteArray = BAI->ByteArray; - Type *Ty = BAI->ByteArray->getValueType(); - if (!LinkerSubsectionsViaSymbols && AvoidReuse) { - // Each use of the byte array uses a different alias. This makes the - // backend less likely to reuse previously computed byte array addresses, - // improving the security of the CFI mechanism based on this pass. - ByteArray = GlobalAlias::create(BAI->ByteArray->getValueType(), 0, - GlobalValue::PrivateLinkage, "bits_use", - ByteArray, M); - } - - Value *ByteAddr = B.CreateGEP(Ty, ByteArray, BitOffset); - Value *Byte = B.CreateLoad(ByteAddr); - - Value *ByteAndMask = B.CreateAnd(Byte, BAI->Mask); - return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0)); - } -} - -/// Lower a llvm.bitset.test call to its implementation. Returns the value to -/// replace the call with. -Value *LowerBitSets::lowerBitSetCall( - CallInst *CI, BitSetInfo &BSI, ByteArrayInfo *&BAI, - Constant *CombinedGlobalIntAddr, - const DenseMap<GlobalObject *, uint64_t> &GlobalLayout) { - Value *Ptr = CI->getArgOperand(0); - const DataLayout &DL = M->getDataLayout(); - - if (BSI.containsValue(DL, GlobalLayout, Ptr)) - return ConstantInt::getTrue(M->getContext()); - - Constant *OffsetedGlobalAsInt = ConstantExpr::getAdd( - CombinedGlobalIntAddr, ConstantInt::get(IntPtrTy, BSI.ByteOffset)); - - BasicBlock *InitialBB = CI->getParent(); - - IRBuilder<> B(CI); - - Value *PtrAsInt = B.CreatePtrToInt(Ptr, IntPtrTy); - - if (BSI.isSingleOffset()) - return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt); - - Value *PtrOffset = B.CreateSub(PtrAsInt, OffsetedGlobalAsInt); - - Value *BitOffset; - if (BSI.AlignLog2 == 0) { - BitOffset = PtrOffset; - } else { - // We need to check that the offset both falls within our range and is - // suitably aligned. We can check both properties at the same time by - // performing a right rotate by log2(alignment) followed by an integer - // comparison against the bitset size. The rotate will move the lower - // order bits that need to be zero into the higher order bits of the - // result, causing the comparison to fail if they are nonzero. The rotate - // also conveniently gives us a bit offset to use during the load from - // the bitset. - Value *OffsetSHR = - B.CreateLShr(PtrOffset, ConstantInt::get(IntPtrTy, BSI.AlignLog2)); - Value *OffsetSHL = B.CreateShl( - PtrOffset, - ConstantInt::get(IntPtrTy, DL.getPointerSizeInBits(0) - BSI.AlignLog2)); - BitOffset = B.CreateOr(OffsetSHR, OffsetSHL); - } - - Constant *BitSizeConst = ConstantInt::get(IntPtrTy, BSI.BitSize); - Value *OffsetInRange = B.CreateICmpULT(BitOffset, BitSizeConst); - - // If the bit set is all ones, testing against it is unnecessary. - if (BSI.isAllOnes()) - return OffsetInRange; - - TerminatorInst *Term = SplitBlockAndInsertIfThen(OffsetInRange, CI, false); - IRBuilder<> ThenB(Term); - - // Now that we know that the offset is in range and aligned, load the - // appropriate bit from the bitset. - Value *Bit = createBitSetTest(ThenB, BSI, BAI, BitOffset); - - // The value we want is 0 if we came directly from the initial block - // (having failed the range or alignment checks), or the loaded bit if - // we came from the block in which we loaded it. - B.SetInsertPoint(CI); - PHINode *P = B.CreatePHI(Int1Ty, 2); - P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB); - P->addIncoming(Bit, ThenB.GetInsertBlock()); - return P; -} - -/// Given a disjoint set of bitsets and globals, layout the globals, build the -/// bit sets and lower the llvm.bitset.test calls. -void LowerBitSets::buildBitSetsFromGlobalVariables( - ArrayRef<Metadata *> BitSets, ArrayRef<GlobalVariable *> Globals) { - // Build a new global with the combined contents of the referenced globals. - // This global is a struct whose even-indexed elements contain the original - // contents of the referenced globals and whose odd-indexed elements contain - // any padding required to align the next element to the next power of 2. - std::vector<Constant *> GlobalInits; - const DataLayout &DL = M->getDataLayout(); - for (GlobalVariable *G : Globals) { - GlobalInits.push_back(G->getInitializer()); - uint64_t InitSize = DL.getTypeAllocSize(G->getValueType()); - - // Compute the amount of padding required. - uint64_t Padding = NextPowerOf2(InitSize - 1) - InitSize; - - // Cap at 128 was found experimentally to have a good data/instruction - // overhead tradeoff. - if (Padding > 128) - Padding = RoundUpToAlignment(InitSize, 128) - InitSize; - - GlobalInits.push_back( - ConstantAggregateZero::get(ArrayType::get(Int8Ty, Padding))); - } - if (!GlobalInits.empty()) - GlobalInits.pop_back(); - Constant *NewInit = ConstantStruct::getAnon(M->getContext(), GlobalInits); - auto *CombinedGlobal = - new GlobalVariable(*M, NewInit->getType(), /*isConstant=*/true, - GlobalValue::PrivateLinkage, NewInit); - - StructType *NewTy = cast<StructType>(NewInit->getType()); - const StructLayout *CombinedGlobalLayout = DL.getStructLayout(NewTy); - - // Compute the offsets of the original globals within the new global. - DenseMap<GlobalObject *, uint64_t> GlobalLayout; - for (unsigned I = 0; I != Globals.size(); ++I) - // Multiply by 2 to account for padding elements. - GlobalLayout[Globals[I]] = CombinedGlobalLayout->getElementOffset(I * 2); - - lowerBitSetCalls(BitSets, CombinedGlobal, GlobalLayout); - - // Build aliases pointing to offsets into the combined global for each - // global from which we built the combined global, and replace references - // to the original globals with references to the aliases. - for (unsigned I = 0; I != Globals.size(); ++I) { - // Multiply by 2 to account for padding elements. - Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0), - ConstantInt::get(Int32Ty, I * 2)}; - Constant *CombinedGlobalElemPtr = ConstantExpr::getGetElementPtr( - NewInit->getType(), CombinedGlobal, CombinedGlobalIdxs); - if (LinkerSubsectionsViaSymbols) { - Globals[I]->replaceAllUsesWith(CombinedGlobalElemPtr); - } else { - assert(Globals[I]->getType()->getAddressSpace() == 0); - GlobalAlias *GAlias = GlobalAlias::create(NewTy->getElementType(I * 2), 0, - Globals[I]->getLinkage(), "", - CombinedGlobalElemPtr, M); - GAlias->setVisibility(Globals[I]->getVisibility()); - GAlias->takeName(Globals[I]); - Globals[I]->replaceAllUsesWith(GAlias); - } - Globals[I]->eraseFromParent(); - } -} - -void LowerBitSets::lowerBitSetCalls( - ArrayRef<Metadata *> BitSets, Constant *CombinedGlobalAddr, - const DenseMap<GlobalObject *, uint64_t> &GlobalLayout) { - Constant *CombinedGlobalIntAddr = - ConstantExpr::getPtrToInt(CombinedGlobalAddr, IntPtrTy); - - // For each bitset in this disjoint set... - for (Metadata *BS : BitSets) { - // Build the bitset. - BitSetInfo BSI = buildBitSet(BS, GlobalLayout); - DEBUG({ - if (auto BSS = dyn_cast<MDString>(BS)) - dbgs() << BSS->getString() << ": "; - else - dbgs() << "<unnamed>: "; - BSI.print(dbgs()); - }); - - ByteArrayInfo *BAI = nullptr; - - // Lower each call to llvm.bitset.test for this bitset. - for (CallInst *CI : BitSetTestCallSites[BS]) { - ++NumBitSetCallsLowered; - Value *Lowered = - lowerBitSetCall(CI, BSI, BAI, CombinedGlobalIntAddr, GlobalLayout); - CI->replaceAllUsesWith(Lowered); - CI->eraseFromParent(); - } - } -} - -void LowerBitSets::verifyBitSetMDNode(MDNode *Op) { - if (Op->getNumOperands() != 3) - report_fatal_error( - "All operands of llvm.bitsets metadata must have 3 elements"); - if (!Op->getOperand(1)) - return; - - auto OpConstMD = dyn_cast<ConstantAsMetadata>(Op->getOperand(1)); - if (!OpConstMD) - report_fatal_error("Bit set element must be a constant"); - auto OpGlobal = dyn_cast<GlobalObject>(OpConstMD->getValue()); - if (!OpGlobal) - return; - - if (OpGlobal->isThreadLocal()) - report_fatal_error("Bit set element may not be thread-local"); - if (OpGlobal->hasSection()) - report_fatal_error("Bit set element may not have an explicit section"); - - if (isa<GlobalVariable>(OpGlobal) && OpGlobal->isDeclarationForLinker()) - report_fatal_error("Bit set global var element must be a definition"); - - auto OffsetConstMD = dyn_cast<ConstantAsMetadata>(Op->getOperand(2)); - if (!OffsetConstMD) - report_fatal_error("Bit set element offset must be a constant"); - auto OffsetInt = dyn_cast<ConstantInt>(OffsetConstMD->getValue()); - if (!OffsetInt) - report_fatal_error("Bit set element offset must be an integer constant"); -} - -static const unsigned kX86JumpTableEntrySize = 8; - -unsigned LowerBitSets::getJumpTableEntrySize() { - if (Arch != Triple::x86 && Arch != Triple::x86_64) - report_fatal_error("Unsupported architecture for jump tables"); - - return kX86JumpTableEntrySize; -} - -// Create a constant representing a jump table entry for the target. This -// consists of an instruction sequence containing a relative branch to Dest. The -// constant will be laid out at address Src+(Len*Distance) where Len is the -// target-specific jump table entry size. -Constant *LowerBitSets::createJumpTableEntry(GlobalObject *Src, Function *Dest, - unsigned Distance) { - if (Arch != Triple::x86 && Arch != Triple::x86_64) - report_fatal_error("Unsupported architecture for jump tables"); - - const unsigned kJmpPCRel32Code = 0xe9; - const unsigned kInt3Code = 0xcc; - - ConstantInt *Jmp = ConstantInt::get(Int8Ty, kJmpPCRel32Code); - - // Build a constant representing the displacement between the constant's - // address and Dest. This will resolve to a PC32 relocation referring to Dest. - Constant *DestInt = ConstantExpr::getPtrToInt(Dest, IntPtrTy); - Constant *SrcInt = ConstantExpr::getPtrToInt(Src, IntPtrTy); - Constant *Disp = ConstantExpr::getSub(DestInt, SrcInt); - ConstantInt *DispOffset = - ConstantInt::get(IntPtrTy, Distance * kX86JumpTableEntrySize + 5); - Constant *OffsetedDisp = ConstantExpr::getSub(Disp, DispOffset); - OffsetedDisp = ConstantExpr::getTruncOrBitCast(OffsetedDisp, Int32Ty); - - ConstantInt *Int3 = ConstantInt::get(Int8Ty, kInt3Code); - - Constant *Fields[] = { - Jmp, OffsetedDisp, Int3, Int3, Int3, - }; - return ConstantStruct::getAnon(Fields, /*Packed=*/true); -} - -Type *LowerBitSets::getJumpTableEntryType() { - if (Arch != Triple::x86 && Arch != Triple::x86_64) - report_fatal_error("Unsupported architecture for jump tables"); - - return StructType::get(M->getContext(), - {Int8Ty, Int32Ty, Int8Ty, Int8Ty, Int8Ty}, - /*Packed=*/true); -} - -/// Given a disjoint set of bitsets and functions, build a jump table for the -/// functions, build the bit sets and lower the llvm.bitset.test calls. -void LowerBitSets::buildBitSetsFromFunctions(ArrayRef<Metadata *> BitSets, - ArrayRef<Function *> Functions) { - // Unlike the global bitset builder, the function bitset builder cannot - // re-arrange functions in a particular order and base its calculations on the - // layout of the functions' entry points, as we have no idea how large a - // particular function will end up being (the size could even depend on what - // this pass does!) Instead, we build a jump table, which is a block of code - // consisting of one branch instruction for each of the functions in the bit - // set that branches to the target function, and redirect any taken function - // addresses to the corresponding jump table entry. In the object file's - // symbol table, the symbols for the target functions also refer to the jump - // table entries, so that addresses taken outside the module will pass any - // verification done inside the module. - // - // In more concrete terms, suppose we have three functions f, g, h which are - // members of a single bitset, and a function foo that returns their - // addresses: - // - // f: - // mov 0, %eax - // ret - // - // g: - // mov 1, %eax - // ret - // - // h: - // mov 2, %eax - // ret - // - // foo: - // mov f, %eax - // mov g, %edx - // mov h, %ecx - // ret - // - // To create a jump table for these functions, we instruct the LLVM code - // generator to output a jump table in the .text section. This is done by - // representing the instructions in the jump table as an LLVM constant and - // placing them in a global variable in the .text section. The end result will - // (conceptually) look like this: - // - // f: - // jmp .Ltmp0 ; 5 bytes - // int3 ; 1 byte - // int3 ; 1 byte - // int3 ; 1 byte - // - // g: - // jmp .Ltmp1 ; 5 bytes - // int3 ; 1 byte - // int3 ; 1 byte - // int3 ; 1 byte - // - // h: - // jmp .Ltmp2 ; 5 bytes - // int3 ; 1 byte - // int3 ; 1 byte - // int3 ; 1 byte - // - // .Ltmp0: - // mov 0, %eax - // ret - // - // .Ltmp1: - // mov 1, %eax - // ret - // - // .Ltmp2: - // mov 2, %eax - // ret - // - // foo: - // mov f, %eax - // mov g, %edx - // mov h, %ecx - // ret - // - // Because the addresses of f, g, h are evenly spaced at a power of 2, in the - // normal case the check can be carried out using the same kind of simple - // arithmetic that we normally use for globals. - - assert(!Functions.empty()); - - // Build a simple layout based on the regular layout of jump tables. - DenseMap<GlobalObject *, uint64_t> GlobalLayout; - unsigned EntrySize = getJumpTableEntrySize(); - for (unsigned I = 0; I != Functions.size(); ++I) - GlobalLayout[Functions[I]] = I * EntrySize; - - // Create a constant to hold the jump table. - ArrayType *JumpTableType = - ArrayType::get(getJumpTableEntryType(), Functions.size()); - auto JumpTable = new GlobalVariable(*M, JumpTableType, - /*isConstant=*/true, - GlobalValue::PrivateLinkage, nullptr); - JumpTable->setSection(ObjectFormat == Triple::MachO - ? "__TEXT,__text,regular,pure_instructions" - : ".text"); - lowerBitSetCalls(BitSets, JumpTable, GlobalLayout); - - // Build aliases pointing to offsets into the jump table, and replace - // references to the original functions with references to the aliases. - for (unsigned I = 0; I != Functions.size(); ++I) { - Constant *CombinedGlobalElemPtr = ConstantExpr::getBitCast( - ConstantExpr::getGetElementPtr( - JumpTableType, JumpTable, - ArrayRef<Constant *>{ConstantInt::get(IntPtrTy, 0), - ConstantInt::get(IntPtrTy, I)}), - Functions[I]->getType()); - if (LinkerSubsectionsViaSymbols || Functions[I]->isDeclarationForLinker()) { - Functions[I]->replaceAllUsesWith(CombinedGlobalElemPtr); - } else { - assert(Functions[I]->getType()->getAddressSpace() == 0); - GlobalAlias *GAlias = GlobalAlias::create(Functions[I]->getValueType(), 0, - Functions[I]->getLinkage(), "", - CombinedGlobalElemPtr, M); - GAlias->setVisibility(Functions[I]->getVisibility()); - GAlias->takeName(Functions[I]); - Functions[I]->replaceAllUsesWith(GAlias); - } - if (!Functions[I]->isDeclarationForLinker()) - Functions[I]->setLinkage(GlobalValue::PrivateLinkage); - } - - // Build and set the jump table's initializer. - std::vector<Constant *> JumpTableEntries; - for (unsigned I = 0; I != Functions.size(); ++I) - JumpTableEntries.push_back( - createJumpTableEntry(JumpTable, Functions[I], I)); - JumpTable->setInitializer( - ConstantArray::get(JumpTableType, JumpTableEntries)); -} - -void LowerBitSets::buildBitSetsFromDisjointSet( - ArrayRef<Metadata *> BitSets, ArrayRef<GlobalObject *> Globals) { - llvm::DenseMap<Metadata *, uint64_t> BitSetIndices; - llvm::DenseMap<GlobalObject *, uint64_t> GlobalIndices; - for (unsigned I = 0; I != BitSets.size(); ++I) - BitSetIndices[BitSets[I]] = I; - for (unsigned I = 0; I != Globals.size(); ++I) - GlobalIndices[Globals[I]] = I; - - // For each bitset, build a set of indices that refer to globals referenced by - // the bitset. - std::vector<std::set<uint64_t>> BitSetMembers(BitSets.size()); - if (BitSetNM) { - for (MDNode *Op : BitSetNM->operands()) { - // Op = { bitset name, global, offset } - if (!Op->getOperand(1)) - continue; - auto I = BitSetIndices.find(Op->getOperand(0)); - if (I == BitSetIndices.end()) - continue; - - auto OpGlobal = dyn_cast<GlobalObject>( - cast<ConstantAsMetadata>(Op->getOperand(1))->getValue()); - if (!OpGlobal) - continue; - BitSetMembers[I->second].insert(GlobalIndices[OpGlobal]); - } - } - - // Order the sets of indices by size. The GlobalLayoutBuilder works best - // when given small index sets first. - std::stable_sort( - BitSetMembers.begin(), BitSetMembers.end(), - [](const std::set<uint64_t> &O1, const std::set<uint64_t> &O2) { - return O1.size() < O2.size(); - }); - - // Create a GlobalLayoutBuilder and provide it with index sets as layout - // fragments. The GlobalLayoutBuilder tries to lay out members of fragments as - // close together as possible. - GlobalLayoutBuilder GLB(Globals.size()); - for (auto &&MemSet : BitSetMembers) - GLB.addFragment(MemSet); - - // Build the bitsets from this disjoint set. - if (Globals.empty() || isa<GlobalVariable>(Globals[0])) { - // Build a vector of global variables with the computed layout. - std::vector<GlobalVariable *> OrderedGVs(Globals.size()); - auto OGI = OrderedGVs.begin(); - for (auto &&F : GLB.Fragments) { - for (auto &&Offset : F) { - auto GV = dyn_cast<GlobalVariable>(Globals[Offset]); - if (!GV) - report_fatal_error( - "Bit set may not contain both global variables and functions"); - *OGI++ = GV; - } - } - - buildBitSetsFromGlobalVariables(BitSets, OrderedGVs); - } else { - // Build a vector of functions with the computed layout. - std::vector<Function *> OrderedFns(Globals.size()); - auto OFI = OrderedFns.begin(); - for (auto &&F : GLB.Fragments) { - for (auto &&Offset : F) { - auto Fn = dyn_cast<Function>(Globals[Offset]); - if (!Fn) - report_fatal_error( - "Bit set may not contain both global variables and functions"); - *OFI++ = Fn; - } - } - - buildBitSetsFromFunctions(BitSets, OrderedFns); - } -} - -/// Lower all bit sets in this module. -bool LowerBitSets::buildBitSets() { - Function *BitSetTestFunc = - M->getFunction(Intrinsic::getName(Intrinsic::bitset_test)); - if (!BitSetTestFunc) - return false; - - // Equivalence class set containing bitsets and the globals they reference. - // This is used to partition the set of bitsets in the module into disjoint - // sets. - typedef EquivalenceClasses<PointerUnion<GlobalObject *, Metadata *>> - GlobalClassesTy; - GlobalClassesTy GlobalClasses; - - // Verify the bitset metadata and build a mapping from bitset identifiers to - // their last observed index in BitSetNM. This will used later to - // deterministically order the list of bitset identifiers. - llvm::DenseMap<Metadata *, unsigned> BitSetIdIndices; - if (BitSetNM) { - for (unsigned I = 0, E = BitSetNM->getNumOperands(); I != E; ++I) { - MDNode *Op = BitSetNM->getOperand(I); - verifyBitSetMDNode(Op); - BitSetIdIndices[Op->getOperand(0)] = I; - } - } - - for (const Use &U : BitSetTestFunc->uses()) { - auto CI = cast<CallInst>(U.getUser()); - - auto BitSetMDVal = dyn_cast<MetadataAsValue>(CI->getArgOperand(1)); - if (!BitSetMDVal) - report_fatal_error( - "Second argument of llvm.bitset.test must be metadata"); - auto BitSet = BitSetMDVal->getMetadata(); - - // Add the call site to the list of call sites for this bit set. We also use - // BitSetTestCallSites to keep track of whether we have seen this bit set - // before. If we have, we don't need to re-add the referenced globals to the - // equivalence class. - std::pair<DenseMap<Metadata *, std::vector<CallInst *>>::iterator, - bool> Ins = - BitSetTestCallSites.insert( - std::make_pair(BitSet, std::vector<CallInst *>())); - Ins.first->second.push_back(CI); - if (!Ins.second) - continue; - - // Add the bitset to the equivalence class. - GlobalClassesTy::iterator GCI = GlobalClasses.insert(BitSet); - GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI); - - if (!BitSetNM) - continue; - - // Add the referenced globals to the bitset's equivalence class. - for (MDNode *Op : BitSetNM->operands()) { - if (Op->getOperand(0) != BitSet || !Op->getOperand(1)) - continue; - - auto OpGlobal = dyn_cast<GlobalObject>( - cast<ConstantAsMetadata>(Op->getOperand(1))->getValue()); - if (!OpGlobal) - continue; - - CurSet = GlobalClasses.unionSets( - CurSet, GlobalClasses.findLeader(GlobalClasses.insert(OpGlobal))); - } - } - - if (GlobalClasses.empty()) - return false; - - // Build a list of disjoint sets ordered by their maximum BitSetNM index - // for determinism. - std::vector<std::pair<GlobalClassesTy::iterator, unsigned>> Sets; - for (GlobalClassesTy::iterator I = GlobalClasses.begin(), - E = GlobalClasses.end(); - I != E; ++I) { - if (!I->isLeader()) continue; - ++NumBitSetDisjointSets; - - unsigned MaxIndex = 0; - for (GlobalClassesTy::member_iterator MI = GlobalClasses.member_begin(I); - MI != GlobalClasses.member_end(); ++MI) { - if ((*MI).is<Metadata *>()) - MaxIndex = std::max(MaxIndex, BitSetIdIndices[MI->get<Metadata *>()]); - } - Sets.emplace_back(I, MaxIndex); - } - std::sort(Sets.begin(), Sets.end(), - [](const std::pair<GlobalClassesTy::iterator, unsigned> &S1, - const std::pair<GlobalClassesTy::iterator, unsigned> &S2) { - return S1.second < S2.second; - }); - - // For each disjoint set we found... - for (const auto &S : Sets) { - // Build the list of bitsets in this disjoint set. - std::vector<Metadata *> BitSets; - std::vector<GlobalObject *> Globals; - for (GlobalClassesTy::member_iterator MI = - GlobalClasses.member_begin(S.first); - MI != GlobalClasses.member_end(); ++MI) { - if ((*MI).is<Metadata *>()) - BitSets.push_back(MI->get<Metadata *>()); - else - Globals.push_back(MI->get<GlobalObject *>()); - } - - // Order bitsets by BitSetNM index for determinism. This ordering is stable - // as there is a one-to-one mapping between metadata and indices. - std::sort(BitSets.begin(), BitSets.end(), [&](Metadata *M1, Metadata *M2) { - return BitSetIdIndices[M1] < BitSetIdIndices[M2]; - }); - - // Lower the bitsets in this disjoint set. - buildBitSetsFromDisjointSet(BitSets, Globals); - } - - allocateByteArrays(); - - return true; -} - -bool LowerBitSets::eraseBitSetMetadata() { - if (!BitSetNM) - return false; - - M->eraseNamedMetadata(BitSetNM); - return true; -} - -bool LowerBitSets::runOnModule(Module &M) { - bool Changed = buildBitSets(); - Changed |= eraseBitSetMetadata(); - return Changed; -} diff --git a/gnu/llvm/lib/Transforms/IPO/Makefile b/gnu/llvm/lib/Transforms/IPO/Makefile deleted file mode 100644 index 5c42374139a..00000000000 --- a/gnu/llvm/lib/Transforms/IPO/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Transforms/IPO/Makefile -------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMipo -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Transforms/InstCombine/Makefile b/gnu/llvm/lib/Transforms/InstCombine/Makefile deleted file mode 100644 index 0c488e78b6d..00000000000 --- a/gnu/llvm/lib/Transforms/InstCombine/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Transforms/InstCombine/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMInstCombine -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Transforms/Instrumentation/Makefile b/gnu/llvm/lib/Transforms/Instrumentation/Makefile deleted file mode 100644 index 6cbc7a9cd88..00000000000 --- a/gnu/llvm/lib/Transforms/Instrumentation/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Transforms/Instrumentation/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMInstrumentation -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Transforms/Instrumentation/SafeStack.cpp b/gnu/llvm/lib/Transforms/Instrumentation/SafeStack.cpp deleted file mode 100644 index abed465f102..00000000000 --- a/gnu/llvm/lib/Transforms/Instrumentation/SafeStack.cpp +++ /dev/null @@ -1,760 +0,0 @@ -//===-- SafeStack.cpp - Safe Stack Insertion ------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass splits the stack into the safe stack (kept as-is for LLVM backend) -// and the unsafe stack (explicitly allocated and managed through the runtime -// support library). -// -// http://clang.llvm.org/docs/SafeStack.html -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/Instrumentation.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Analysis/ScalarEvolution.h" -#include "llvm/Analysis/ScalarEvolutionExpressions.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Module.h" -#include "llvm/Pass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_os_ostream.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Target/TargetSubtargetInfo.h" -#include "llvm/Transforms/Utils/Local.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" - -using namespace llvm; - -#define DEBUG_TYPE "safestack" - -enum UnsafeStackPtrStorageVal { ThreadLocalUSP, SingleThreadUSP }; - -static cl::opt<UnsafeStackPtrStorageVal> USPStorage("safe-stack-usp-storage", - cl::Hidden, cl::init(ThreadLocalUSP), - cl::desc("Type of storage for the unsafe stack pointer"), - cl::values(clEnumValN(ThreadLocalUSP, "thread-local", - "Thread-local storage"), - clEnumValN(SingleThreadUSP, "single-thread", - "Non-thread-local storage"), - clEnumValEnd)); - -namespace llvm { - -STATISTIC(NumFunctions, "Total number of functions"); -STATISTIC(NumUnsafeStackFunctions, "Number of functions with unsafe stack"); -STATISTIC(NumUnsafeStackRestorePointsFunctions, - "Number of functions that use setjmp or exceptions"); - -STATISTIC(NumAllocas, "Total number of allocas"); -STATISTIC(NumUnsafeStaticAllocas, "Number of unsafe static allocas"); -STATISTIC(NumUnsafeDynamicAllocas, "Number of unsafe dynamic allocas"); -STATISTIC(NumUnsafeByValArguments, "Number of unsafe byval arguments"); -STATISTIC(NumUnsafeStackRestorePoints, "Number of setjmps and landingpads"); - -} // namespace llvm - -namespace { - -/// Rewrite an SCEV expression for a memory access address to an expression that -/// represents offset from the given alloca. -/// -/// The implementation simply replaces all mentions of the alloca with zero. -class AllocaOffsetRewriter : public SCEVRewriteVisitor<AllocaOffsetRewriter> { - const Value *AllocaPtr; - -public: - AllocaOffsetRewriter(ScalarEvolution &SE, const Value *AllocaPtr) - : SCEVRewriteVisitor(SE), AllocaPtr(AllocaPtr) {} - - const SCEV *visitUnknown(const SCEVUnknown *Expr) { - if (Expr->getValue() == AllocaPtr) - return SE.getZero(Expr->getType()); - return Expr; - } -}; - -/// The SafeStack pass splits the stack of each function into the safe -/// stack, which is only accessed through memory safe dereferences (as -/// determined statically), and the unsafe stack, which contains all -/// local variables that are accessed in ways that we can't prove to -/// be safe. -class SafeStack : public FunctionPass { - const TargetMachine *TM; - const TargetLoweringBase *TL; - const DataLayout *DL; - ScalarEvolution *SE; - - Type *StackPtrTy; - Type *IntPtrTy; - Type *Int32Ty; - Type *Int8Ty; - - Value *UnsafeStackPtr = nullptr; - - /// Unsafe stack alignment. Each stack frame must ensure that the stack is - /// aligned to this value. We need to re-align the unsafe stack if the - /// alignment of any object on the stack exceeds this value. - /// - /// 16 seems like a reasonable upper bound on the alignment of objects that we - /// might expect to appear on the stack on most common targets. - enum { StackAlignment = 16 }; - - /// \brief Build a value representing a pointer to the unsafe stack pointer. - Value *getOrCreateUnsafeStackPtr(IRBuilder<> &IRB, Function &F); - - /// \brief Find all static allocas, dynamic allocas, return instructions and - /// stack restore points (exception unwind blocks and setjmp calls) in the - /// given function and append them to the respective vectors. - void findInsts(Function &F, SmallVectorImpl<AllocaInst *> &StaticAllocas, - SmallVectorImpl<AllocaInst *> &DynamicAllocas, - SmallVectorImpl<Argument *> &ByValArguments, - SmallVectorImpl<ReturnInst *> &Returns, - SmallVectorImpl<Instruction *> &StackRestorePoints); - - /// \brief Calculate the allocation size of a given alloca. Returns 0 if the - /// size can not be statically determined. - uint64_t getStaticAllocaAllocationSize(const AllocaInst* AI); - - /// \brief Allocate space for all static allocas in \p StaticAllocas, - /// replace allocas with pointers into the unsafe stack and generate code to - /// restore the stack pointer before all return instructions in \p Returns. - /// - /// \returns A pointer to the top of the unsafe stack after all unsafe static - /// allocas are allocated. - Value *moveStaticAllocasToUnsafeStack(IRBuilder<> &IRB, Function &F, - ArrayRef<AllocaInst *> StaticAllocas, - ArrayRef<Argument *> ByValArguments, - ArrayRef<ReturnInst *> Returns); - - /// \brief Generate code to restore the stack after all stack restore points - /// in \p StackRestorePoints. - /// - /// \returns A local variable in which to maintain the dynamic top of the - /// unsafe stack if needed. - AllocaInst * - createStackRestorePoints(IRBuilder<> &IRB, Function &F, - ArrayRef<Instruction *> StackRestorePoints, - Value *StaticTop, bool NeedDynamicTop); - - /// \brief Replace all allocas in \p DynamicAllocas with code to allocate - /// space dynamically on the unsafe stack and store the dynamic unsafe stack - /// top to \p DynamicTop if non-null. - void moveDynamicAllocasToUnsafeStack(Function &F, Value *UnsafeStackPtr, - AllocaInst *DynamicTop, - ArrayRef<AllocaInst *> DynamicAllocas); - - bool IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize); - - bool IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U, - const Value *AllocaPtr, uint64_t AllocaSize); - bool IsAccessSafe(Value *Addr, uint64_t Size, const Value *AllocaPtr, - uint64_t AllocaSize); - -public: - static char ID; // Pass identification, replacement for typeid. - SafeStack(const TargetMachine *TM) - : FunctionPass(ID), TM(TM), TL(nullptr), DL(nullptr) { - initializeSafeStackPass(*PassRegistry::getPassRegistry()); - } - SafeStack() : SafeStack(nullptr) {} - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<ScalarEvolutionWrapperPass>(); - } - - bool doInitialization(Module &M) override { - DL = &M.getDataLayout(); - - StackPtrTy = Type::getInt8PtrTy(M.getContext()); - IntPtrTy = DL->getIntPtrType(M.getContext()); - Int32Ty = Type::getInt32Ty(M.getContext()); - Int8Ty = Type::getInt8Ty(M.getContext()); - - return false; - } - - bool runOnFunction(Function &F) override; -}; // class SafeStack - -uint64_t SafeStack::getStaticAllocaAllocationSize(const AllocaInst* AI) { - uint64_t Size = DL->getTypeAllocSize(AI->getAllocatedType()); - if (AI->isArrayAllocation()) { - auto C = dyn_cast<ConstantInt>(AI->getArraySize()); - if (!C) - return 0; - Size *= C->getZExtValue(); - } - return Size; -} - -bool SafeStack::IsAccessSafe(Value *Addr, uint64_t AccessSize, - const Value *AllocaPtr, uint64_t AllocaSize) { - AllocaOffsetRewriter Rewriter(*SE, AllocaPtr); - const SCEV *Expr = Rewriter.visit(SE->getSCEV(Addr)); - - uint64_t BitWidth = SE->getTypeSizeInBits(Expr->getType()); - ConstantRange AccessStartRange = SE->getUnsignedRange(Expr); - ConstantRange SizeRange = - ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, AccessSize)); - ConstantRange AccessRange = AccessStartRange.add(SizeRange); - ConstantRange AllocaRange = - ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, AllocaSize)); - bool Safe = AllocaRange.contains(AccessRange); - - DEBUG(dbgs() << "[SafeStack] " - << (isa<AllocaInst>(AllocaPtr) ? "Alloca " : "ByValArgument ") - << *AllocaPtr << "\n" - << " Access " << *Addr << "\n" - << " SCEV " << *Expr - << " U: " << SE->getUnsignedRange(Expr) - << ", S: " << SE->getSignedRange(Expr) << "\n" - << " Range " << AccessRange << "\n" - << " AllocaRange " << AllocaRange << "\n" - << " " << (Safe ? "safe" : "unsafe") << "\n"); - - return Safe; -} - -bool SafeStack::IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U, - const Value *AllocaPtr, - uint64_t AllocaSize) { - // All MemIntrinsics have destination address in Arg0 and size in Arg2. - if (MI->getRawDest() != U) return true; - const auto *Len = dyn_cast<ConstantInt>(MI->getLength()); - // Non-constant size => unsafe. FIXME: try SCEV getRange. - if (!Len) return false; - return IsAccessSafe(U, Len->getZExtValue(), AllocaPtr, AllocaSize); -} - -/// Check whether a given allocation must be put on the safe -/// stack or not. The function analyzes all uses of AI and checks whether it is -/// only accessed in a memory safe way (as decided statically). -bool SafeStack::IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize) { - // Go through all uses of this alloca and check whether all accesses to the - // allocated object are statically known to be memory safe and, hence, the - // object can be placed on the safe stack. - SmallPtrSet<const Value *, 16> Visited; - SmallVector<const Value *, 8> WorkList; - WorkList.push_back(AllocaPtr); - - // A DFS search through all uses of the alloca in bitcasts/PHI/GEPs/etc. - while (!WorkList.empty()) { - const Value *V = WorkList.pop_back_val(); - for (const Use &UI : V->uses()) { - auto I = cast<const Instruction>(UI.getUser()); - assert(V == UI.get()); - - switch (I->getOpcode()) { - case Instruction::Load: { - if (!IsAccessSafe(UI, DL->getTypeStoreSize(I->getType()), AllocaPtr, - AllocaSize)) - return false; - break; - } - case Instruction::VAArg: - // "va-arg" from a pointer is safe. - break; - case Instruction::Store: { - if (V == I->getOperand(0)) { - // Stored the pointer - conservatively assume it may be unsafe. - DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr - << "\n store of address: " << *I << "\n"); - return false; - } - - if (!IsAccessSafe(UI, DL->getTypeStoreSize(I->getOperand(0)->getType()), - AllocaPtr, AllocaSize)) - return false; - break; - } - case Instruction::Ret: { - // Information leak. - return false; - } - - case Instruction::Call: - case Instruction::Invoke: { - ImmutableCallSite CS(I); - - if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { - if (II->getIntrinsicID() == Intrinsic::lifetime_start || - II->getIntrinsicID() == Intrinsic::lifetime_end) - continue; - } - - if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) { - if (!IsMemIntrinsicSafe(MI, UI, AllocaPtr, AllocaSize)) { - DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr - << "\n unsafe memintrinsic: " << *I - << "\n"); - return false; - } - continue; - } - - // LLVM 'nocapture' attribute is only set for arguments whose address - // is not stored, passed around, or used in any other non-trivial way. - // We assume that passing a pointer to an object as a 'nocapture - // readnone' argument is safe. - // FIXME: a more precise solution would require an interprocedural - // analysis here, which would look at all uses of an argument inside - // the function being called. - ImmutableCallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end(); - for (ImmutableCallSite::arg_iterator A = B; A != E; ++A) - if (A->get() == V) - if (!(CS.doesNotCapture(A - B) && (CS.doesNotAccessMemory(A - B) || - CS.doesNotAccessMemory()))) { - DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr - << "\n unsafe call: " << *I << "\n"); - return false; - } - continue; - } - - default: - if (Visited.insert(I).second) - WorkList.push_back(cast<const Instruction>(I)); - } - } - } - - // All uses of the alloca are safe, we can place it on the safe stack. - return true; -} - -Value *SafeStack::getOrCreateUnsafeStackPtr(IRBuilder<> &IRB, Function &F) { - // Check if there is a target-specific location for the unsafe stack pointer. - if (TL) - if (Value *V = TL->getSafeStackPointerLocation(IRB)) - return V; - - // Otherwise, assume the target links with compiler-rt, which provides a - // thread-local variable with a magic name. - Module &M = *F.getParent(); - const char *UnsafeStackPtrVar = "__safestack_unsafe_stack_ptr"; - auto UnsafeStackPtr = - dyn_cast_or_null<GlobalVariable>(M.getNamedValue(UnsafeStackPtrVar)); - - bool UseTLS = USPStorage == ThreadLocalUSP; - - if (!UnsafeStackPtr) { - auto TLSModel = UseTLS ? - GlobalValue::InitialExecTLSModel : - GlobalValue::NotThreadLocal; - // The global variable is not defined yet, define it ourselves. - // We use the initial-exec TLS model because we do not support the - // variable living anywhere other than in the main executable. - UnsafeStackPtr = new GlobalVariable( - M, StackPtrTy, false, GlobalValue::ExternalLinkage, nullptr, - UnsafeStackPtrVar, nullptr, TLSModel); - } else { - // The variable exists, check its type and attributes. - if (UnsafeStackPtr->getValueType() != StackPtrTy) - report_fatal_error(Twine(UnsafeStackPtrVar) + " must have void* type"); - if (UseTLS != UnsafeStackPtr->isThreadLocal()) - report_fatal_error(Twine(UnsafeStackPtrVar) + " must " + - (UseTLS ? "" : "not ") + "be thread-local"); - } - return UnsafeStackPtr; -} - -void SafeStack::findInsts(Function &F, - SmallVectorImpl<AllocaInst *> &StaticAllocas, - SmallVectorImpl<AllocaInst *> &DynamicAllocas, - SmallVectorImpl<Argument *> &ByValArguments, - SmallVectorImpl<ReturnInst *> &Returns, - SmallVectorImpl<Instruction *> &StackRestorePoints) { - for (Instruction &I : instructions(&F)) { - if (auto AI = dyn_cast<AllocaInst>(&I)) { - ++NumAllocas; - - uint64_t Size = getStaticAllocaAllocationSize(AI); - if (IsSafeStackAlloca(AI, Size)) - continue; - - if (AI->isStaticAlloca()) { - ++NumUnsafeStaticAllocas; - StaticAllocas.push_back(AI); - } else { - ++NumUnsafeDynamicAllocas; - DynamicAllocas.push_back(AI); - } - } else if (auto RI = dyn_cast<ReturnInst>(&I)) { - Returns.push_back(RI); - } else if (auto CI = dyn_cast<CallInst>(&I)) { - // setjmps require stack restore. - if (CI->getCalledFunction() && CI->canReturnTwice()) - StackRestorePoints.push_back(CI); - } else if (auto LP = dyn_cast<LandingPadInst>(&I)) { - // Exception landing pads require stack restore. - StackRestorePoints.push_back(LP); - } else if (auto II = dyn_cast<IntrinsicInst>(&I)) { - if (II->getIntrinsicID() == Intrinsic::gcroot) - llvm::report_fatal_error( - "gcroot intrinsic not compatible with safestack attribute"); - } - } - for (Argument &Arg : F.args()) { - if (!Arg.hasByValAttr()) - continue; - uint64_t Size = - DL->getTypeStoreSize(Arg.getType()->getPointerElementType()); - if (IsSafeStackAlloca(&Arg, Size)) - continue; - - ++NumUnsafeByValArguments; - ByValArguments.push_back(&Arg); - } -} - -AllocaInst * -SafeStack::createStackRestorePoints(IRBuilder<> &IRB, Function &F, - ArrayRef<Instruction *> StackRestorePoints, - Value *StaticTop, bool NeedDynamicTop) { - if (StackRestorePoints.empty()) - return nullptr; - - // We need the current value of the shadow stack pointer to restore - // after longjmp or exception catching. - - // FIXME: On some platforms this could be handled by the longjmp/exception - // runtime itself. - - AllocaInst *DynamicTop = nullptr; - if (NeedDynamicTop) - // If we also have dynamic alloca's, the stack pointer value changes - // throughout the function. For now we store it in an alloca. - DynamicTop = IRB.CreateAlloca(StackPtrTy, /*ArraySize=*/nullptr, - "unsafe_stack_dynamic_ptr"); - - if (!StaticTop) - // We need the original unsafe stack pointer value, even if there are - // no unsafe static allocas. - StaticTop = IRB.CreateLoad(UnsafeStackPtr, false, "unsafe_stack_ptr"); - - if (NeedDynamicTop) - IRB.CreateStore(StaticTop, DynamicTop); - - // Restore current stack pointer after longjmp/exception catch. - for (Instruction *I : StackRestorePoints) { - ++NumUnsafeStackRestorePoints; - - IRB.SetInsertPoint(I->getNextNode()); - Value *CurrentTop = DynamicTop ? IRB.CreateLoad(DynamicTop) : StaticTop; - IRB.CreateStore(CurrentTop, UnsafeStackPtr); - } - - return DynamicTop; -} - -Value *SafeStack::moveStaticAllocasToUnsafeStack( - IRBuilder<> &IRB, Function &F, ArrayRef<AllocaInst *> StaticAllocas, - ArrayRef<Argument *> ByValArguments, ArrayRef<ReturnInst *> Returns) { - if (StaticAllocas.empty() && ByValArguments.empty()) - return nullptr; - - DIBuilder DIB(*F.getParent()); - - // We explicitly compute and set the unsafe stack layout for all unsafe - // static alloca instructions. We save the unsafe "base pointer" in the - // prologue into a local variable and restore it in the epilogue. - - // Load the current stack pointer (we'll also use it as a base pointer). - // FIXME: use a dedicated register for it ? - Instruction *BasePointer = - IRB.CreateLoad(UnsafeStackPtr, false, "unsafe_stack_ptr"); - assert(BasePointer->getType() == StackPtrTy); - - for (ReturnInst *RI : Returns) { - IRB.SetInsertPoint(RI); - IRB.CreateStore(BasePointer, UnsafeStackPtr); - } - - // Compute maximum alignment among static objects on the unsafe stack. - unsigned MaxAlignment = 0; - for (Argument *Arg : ByValArguments) { - Type *Ty = Arg->getType()->getPointerElementType(); - unsigned Align = std::max((unsigned)DL->getPrefTypeAlignment(Ty), - Arg->getParamAlignment()); - if (Align > MaxAlignment) - MaxAlignment = Align; - } - for (AllocaInst *AI : StaticAllocas) { - Type *Ty = AI->getAllocatedType(); - unsigned Align = - std::max((unsigned)DL->getPrefTypeAlignment(Ty), AI->getAlignment()); - if (Align > MaxAlignment) - MaxAlignment = Align; - } - - if (MaxAlignment > StackAlignment) { - // Re-align the base pointer according to the max requested alignment. - assert(isPowerOf2_32(MaxAlignment)); - IRB.SetInsertPoint(BasePointer->getNextNode()); - BasePointer = cast<Instruction>(IRB.CreateIntToPtr( - IRB.CreateAnd(IRB.CreatePtrToInt(BasePointer, IntPtrTy), - ConstantInt::get(IntPtrTy, ~uint64_t(MaxAlignment - 1))), - StackPtrTy)); - } - - int64_t StaticOffset = 0; // Current stack top. - IRB.SetInsertPoint(BasePointer->getNextNode()); - - for (Argument *Arg : ByValArguments) { - Type *Ty = Arg->getType()->getPointerElementType(); - - uint64_t Size = DL->getTypeStoreSize(Ty); - if (Size == 0) - Size = 1; // Don't create zero-sized stack objects. - - // Ensure the object is properly aligned. - unsigned Align = std::max((unsigned)DL->getPrefTypeAlignment(Ty), - Arg->getParamAlignment()); - - // Add alignment. - // NOTE: we ensure that BasePointer itself is aligned to >= Align. - StaticOffset += Size; - StaticOffset = RoundUpToAlignment(StaticOffset, Align); - - Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8* - ConstantInt::get(Int32Ty, -StaticOffset)); - Value *NewArg = IRB.CreateBitCast(Off, Arg->getType(), - Arg->getName() + ".unsafe-byval"); - - // Replace alloc with the new location. - replaceDbgDeclare(Arg, BasePointer, BasePointer->getNextNode(), DIB, - /*Deref=*/true, -StaticOffset); - Arg->replaceAllUsesWith(NewArg); - IRB.SetInsertPoint(cast<Instruction>(NewArg)->getNextNode()); - IRB.CreateMemCpy(Off, Arg, Size, Arg->getParamAlignment()); - } - - // Allocate space for every unsafe static AllocaInst on the unsafe stack. - for (AllocaInst *AI : StaticAllocas) { - IRB.SetInsertPoint(AI); - - Type *Ty = AI->getAllocatedType(); - uint64_t Size = getStaticAllocaAllocationSize(AI); - if (Size == 0) - Size = 1; // Don't create zero-sized stack objects. - - // Ensure the object is properly aligned. - unsigned Align = - std::max((unsigned)DL->getPrefTypeAlignment(Ty), AI->getAlignment()); - - // Add alignment. - // NOTE: we ensure that BasePointer itself is aligned to >= Align. - StaticOffset += Size; - StaticOffset = RoundUpToAlignment(StaticOffset, Align); - - Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8* - ConstantInt::get(Int32Ty, -StaticOffset)); - Value *NewAI = IRB.CreateBitCast(Off, AI->getType(), AI->getName()); - if (AI->hasName() && isa<Instruction>(NewAI)) - cast<Instruction>(NewAI)->takeName(AI); - - // Replace alloc with the new location. - replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/true, -StaticOffset); - AI->replaceAllUsesWith(NewAI); - AI->eraseFromParent(); - } - - // Re-align BasePointer so that our callees would see it aligned as - // expected. - // FIXME: no need to update BasePointer in leaf functions. - StaticOffset = RoundUpToAlignment(StaticOffset, StackAlignment); - - // Update shadow stack pointer in the function epilogue. - IRB.SetInsertPoint(BasePointer->getNextNode()); - - Value *StaticTop = - IRB.CreateGEP(BasePointer, ConstantInt::get(Int32Ty, -StaticOffset), - "unsafe_stack_static_top"); - IRB.CreateStore(StaticTop, UnsafeStackPtr); - return StaticTop; -} - -void SafeStack::moveDynamicAllocasToUnsafeStack( - Function &F, Value *UnsafeStackPtr, AllocaInst *DynamicTop, - ArrayRef<AllocaInst *> DynamicAllocas) { - DIBuilder DIB(*F.getParent()); - - for (AllocaInst *AI : DynamicAllocas) { - IRBuilder<> IRB(AI); - - // Compute the new SP value (after AI). - Value *ArraySize = AI->getArraySize(); - if (ArraySize->getType() != IntPtrTy) - ArraySize = IRB.CreateIntCast(ArraySize, IntPtrTy, false); - - Type *Ty = AI->getAllocatedType(); - uint64_t TySize = DL->getTypeAllocSize(Ty); - Value *Size = IRB.CreateMul(ArraySize, ConstantInt::get(IntPtrTy, TySize)); - - Value *SP = IRB.CreatePtrToInt(IRB.CreateLoad(UnsafeStackPtr), IntPtrTy); - SP = IRB.CreateSub(SP, Size); - - // Align the SP value to satisfy the AllocaInst, type and stack alignments. - unsigned Align = std::max( - std::max((unsigned)DL->getPrefTypeAlignment(Ty), AI->getAlignment()), - (unsigned)StackAlignment); - - assert(isPowerOf2_32(Align)); - Value *NewTop = IRB.CreateIntToPtr( - IRB.CreateAnd(SP, ConstantInt::get(IntPtrTy, ~uint64_t(Align - 1))), - StackPtrTy); - - // Save the stack pointer. - IRB.CreateStore(NewTop, UnsafeStackPtr); - if (DynamicTop) - IRB.CreateStore(NewTop, DynamicTop); - - Value *NewAI = IRB.CreatePointerCast(NewTop, AI->getType()); - if (AI->hasName() && isa<Instruction>(NewAI)) - NewAI->takeName(AI); - - replaceDbgDeclareForAlloca(AI, NewAI, DIB, /*Deref=*/true); - AI->replaceAllUsesWith(NewAI); - AI->eraseFromParent(); - } - - if (!DynamicAllocas.empty()) { - // Now go through the instructions again, replacing stacksave/stackrestore. - for (inst_iterator It = inst_begin(&F), Ie = inst_end(&F); It != Ie;) { - Instruction *I = &*(It++); - auto II = dyn_cast<IntrinsicInst>(I); - if (!II) - continue; - - if (II->getIntrinsicID() == Intrinsic::stacksave) { - IRBuilder<> IRB(II); - Instruction *LI = IRB.CreateLoad(UnsafeStackPtr); - LI->takeName(II); - II->replaceAllUsesWith(LI); - II->eraseFromParent(); - } else if (II->getIntrinsicID() == Intrinsic::stackrestore) { - IRBuilder<> IRB(II); - Instruction *SI = IRB.CreateStore(II->getArgOperand(0), UnsafeStackPtr); - SI->takeName(II); - assert(II->use_empty()); - II->eraseFromParent(); - } - } - } -} - -bool SafeStack::runOnFunction(Function &F) { - DEBUG(dbgs() << "[SafeStack] Function: " << F.getName() << "\n"); - - if (!F.hasFnAttribute(Attribute::SafeStack)) { - DEBUG(dbgs() << "[SafeStack] safestack is not requested" - " for this function\n"); - return false; - } - - if (F.isDeclaration()) { - DEBUG(dbgs() << "[SafeStack] function definition" - " is not available\n"); - return false; - } - - TL = TM ? TM->getSubtargetImpl(F)->getTargetLowering() : nullptr; - SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); - - { - // Make sure the regular stack protector won't run on this function - // (safestack attribute takes precedence). - AttrBuilder B; - B.addAttribute(Attribute::StackProtect) - .addAttribute(Attribute::StackProtectReq) - .addAttribute(Attribute::StackProtectStrong); - F.removeAttributes( - AttributeSet::FunctionIndex, - AttributeSet::get(F.getContext(), AttributeSet::FunctionIndex, B)); - } - - ++NumFunctions; - - SmallVector<AllocaInst *, 16> StaticAllocas; - SmallVector<AllocaInst *, 4> DynamicAllocas; - SmallVector<Argument *, 4> ByValArguments; - SmallVector<ReturnInst *, 4> Returns; - - // Collect all points where stack gets unwound and needs to be restored - // This is only necessary because the runtime (setjmp and unwind code) is - // not aware of the unsafe stack and won't unwind/restore it prorerly. - // To work around this problem without changing the runtime, we insert - // instrumentation to restore the unsafe stack pointer when necessary. - SmallVector<Instruction *, 4> StackRestorePoints; - - // Find all static and dynamic alloca instructions that must be moved to the - // unsafe stack, all return instructions and stack restore points. - findInsts(F, StaticAllocas, DynamicAllocas, ByValArguments, Returns, - StackRestorePoints); - - if (StaticAllocas.empty() && DynamicAllocas.empty() && - ByValArguments.empty() && StackRestorePoints.empty()) - return false; // Nothing to do in this function. - - if (!StaticAllocas.empty() || !DynamicAllocas.empty() || - !ByValArguments.empty()) - ++NumUnsafeStackFunctions; // This function has the unsafe stack. - - if (!StackRestorePoints.empty()) - ++NumUnsafeStackRestorePointsFunctions; - - IRBuilder<> IRB(&F.front(), F.begin()->getFirstInsertionPt()); - UnsafeStackPtr = getOrCreateUnsafeStackPtr(IRB, F); - - // The top of the unsafe stack after all unsafe static allocas are allocated. - Value *StaticTop = moveStaticAllocasToUnsafeStack(IRB, F, StaticAllocas, - ByValArguments, Returns); - - // Safe stack object that stores the current unsafe stack top. It is updated - // as unsafe dynamic (non-constant-sized) allocas are allocated and freed. - // This is only needed if we need to restore stack pointer after longjmp - // or exceptions, and we have dynamic allocations. - // FIXME: a better alternative might be to store the unsafe stack pointer - // before setjmp / invoke instructions. - AllocaInst *DynamicTop = createStackRestorePoints( - IRB, F, StackRestorePoints, StaticTop, !DynamicAllocas.empty()); - - // Handle dynamic allocas. - moveDynamicAllocasToUnsafeStack(F, UnsafeStackPtr, DynamicTop, - DynamicAllocas); - - DEBUG(dbgs() << "[SafeStack] safestack applied\n"); - return true; -} - -} // anonymous namespace - -char SafeStack::ID = 0; -INITIALIZE_TM_PASS_BEGIN(SafeStack, "safe-stack", - "Safe Stack instrumentation pass", false, false) -INITIALIZE_TM_PASS_END(SafeStack, "safe-stack", - "Safe Stack instrumentation pass", false, false) - -FunctionPass *llvm::createSafeStackPass(const llvm::TargetMachine *TM) { - return new SafeStack(TM); -} diff --git a/gnu/llvm/lib/Transforms/Makefile b/gnu/llvm/lib/Transforms/Makefile deleted file mode 100644 index c390517d07c..00000000000 --- a/gnu/llvm/lib/Transforms/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -##===- lib/Transforms/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -PARALLEL_DIRS = Utils Instrumentation Scalar InstCombine IPO Vectorize Hello ObjCARC - -include $(LEVEL)/Makefile.config - -# No support for plugins on windows targets -ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW Minix)) - PARALLEL_DIRS := $(filter-out Hello, $(PARALLEL_DIRS)) -endif - -include $(LEVEL)/Makefile.common diff --git a/gnu/llvm/lib/Transforms/ObjCARC/Makefile b/gnu/llvm/lib/Transforms/ObjCARC/Makefile deleted file mode 100644 index 2a34e21714f..00000000000 --- a/gnu/llvm/lib/Transforms/ObjCARC/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Transforms/ObjCARC/Makefile ---------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMObjCARCOpts -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Transforms/Scalar/Makefile b/gnu/llvm/lib/Transforms/Scalar/Makefile deleted file mode 100644 index cc42fd00ac7..00000000000 --- a/gnu/llvm/lib/Transforms/Scalar/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Transforms/Scalar/Makefile ----------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMScalarOpts -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/gnu/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp deleted file mode 100644 index 114d22ddf2e..00000000000 --- a/gnu/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ /dev/null @@ -1,2630 +0,0 @@ -//===- ScalarReplAggregates.cpp - Scalar Replacement of Aggregates --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This transformation implements the well known scalar replacement of -// aggregates transformation. This xform breaks up alloca instructions of -// aggregate type (structure or array) into individual alloca instructions for -// each member (if possible). Then, if possible, it transforms the individual -// alloca instructions into nice clean scalar SSA form. -// -// This combines a simple SRoA algorithm with the Mem2Reg algorithm because they -// often interact, especially for C++ programs. As such, iterating between -// SRoA, then Mem2Reg until we run out of things to promote works well. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/Scalar.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/AssumptionCache.h" -#include "llvm/Analysis/Loads.h" -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GetElementPtrTypeIterator.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Operator.h" -#include "llvm/Pass.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Utils/Local.h" -#include "llvm/Transforms/Utils/PromoteMemToReg.h" -#include "llvm/Transforms/Utils/SSAUpdater.h" -using namespace llvm; - -#define DEBUG_TYPE "scalarrepl" - -STATISTIC(NumReplaced, "Number of allocas broken up"); -STATISTIC(NumPromoted, "Number of allocas promoted"); -STATISTIC(NumAdjusted, "Number of scalar allocas adjusted to allow promotion"); -STATISTIC(NumConverted, "Number of aggregates converted to scalar"); - -namespace { -#define SROA SROA_ - struct SROA : public FunctionPass { - SROA(int T, bool hasDT, char &ID, int ST, int AT, int SLT) - : FunctionPass(ID), HasDomTree(hasDT) { - if (T == -1) - SRThreshold = 128; - else - SRThreshold = T; - if (ST == -1) - StructMemberThreshold = 32; - else - StructMemberThreshold = ST; - if (AT == -1) - ArrayElementThreshold = 8; - else - ArrayElementThreshold = AT; - if (SLT == -1) - // Do not limit the scalar integer load size if no threshold is given. - ScalarLoadThreshold = -1; - else - ScalarLoadThreshold = SLT; - } - - bool runOnFunction(Function &F) override; - - bool performScalarRepl(Function &F); - bool performPromotion(Function &F); - - private: - bool HasDomTree; - - /// DeadInsts - Keep track of instructions we have made dead, so that - /// we can remove them after we are done working. - SmallVector<Value*, 32> DeadInsts; - - /// AllocaInfo - When analyzing uses of an alloca instruction, this captures - /// information about the uses. All these fields are initialized to false - /// and set to true when something is learned. - struct AllocaInfo { - /// The alloca to promote. - AllocaInst *AI; - - /// CheckedPHIs - This is a set of verified PHI nodes, to prevent infinite - /// looping and avoid redundant work. - SmallPtrSet<PHINode*, 8> CheckedPHIs; - - /// isUnsafe - This is set to true if the alloca cannot be SROA'd. - bool isUnsafe : 1; - - /// isMemCpySrc - This is true if this aggregate is memcpy'd from. - bool isMemCpySrc : 1; - - /// isMemCpyDst - This is true if this aggregate is memcpy'd into. - bool isMemCpyDst : 1; - - /// hasSubelementAccess - This is true if a subelement of the alloca is - /// ever accessed, or false if the alloca is only accessed with mem - /// intrinsics or load/store that only access the entire alloca at once. - bool hasSubelementAccess : 1; - - /// hasALoadOrStore - This is true if there are any loads or stores to it. - /// The alloca may just be accessed with memcpy, for example, which would - /// not set this. - bool hasALoadOrStore : 1; - - explicit AllocaInfo(AllocaInst *ai) - : AI(ai), isUnsafe(false), isMemCpySrc(false), isMemCpyDst(false), - hasSubelementAccess(false), hasALoadOrStore(false) {} - }; - - /// SRThreshold - The maximum alloca size to considered for SROA. - unsigned SRThreshold; - - /// StructMemberThreshold - The maximum number of members a struct can - /// contain to be considered for SROA. - unsigned StructMemberThreshold; - - /// ArrayElementThreshold - The maximum number of elements an array can - /// have to be considered for SROA. - unsigned ArrayElementThreshold; - - /// ScalarLoadThreshold - The maximum size in bits of scalars to load when - /// converting to scalar - unsigned ScalarLoadThreshold; - - void MarkUnsafe(AllocaInfo &I, Instruction *User) { - I.isUnsafe = true; - DEBUG(dbgs() << " Transformation preventing inst: " << *User << '\n'); - } - - bool isSafeAllocaToScalarRepl(AllocaInst *AI); - - void isSafeForScalarRepl(Instruction *I, uint64_t Offset, AllocaInfo &Info); - void isSafePHISelectUseForScalarRepl(Instruction *User, uint64_t Offset, - AllocaInfo &Info); - void isSafeGEP(GetElementPtrInst *GEPI, uint64_t &Offset, AllocaInfo &Info); - void isSafeMemAccess(uint64_t Offset, uint64_t MemSize, - Type *MemOpType, bool isStore, AllocaInfo &Info, - Instruction *TheAccess, bool AllowWholeAccess); - bool TypeHasComponent(Type *T, uint64_t Offset, uint64_t Size, - const DataLayout &DL); - uint64_t FindElementAndOffset(Type *&T, uint64_t &Offset, Type *&IdxTy, - const DataLayout &DL); - - void DoScalarReplacement(AllocaInst *AI, - std::vector<AllocaInst*> &WorkList); - void DeleteDeadInstructions(); - - void RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, - SmallVectorImpl<AllocaInst *> &NewElts); - void RewriteBitCast(BitCastInst *BC, AllocaInst *AI, uint64_t Offset, - SmallVectorImpl<AllocaInst *> &NewElts); - void RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset, - SmallVectorImpl<AllocaInst *> &NewElts); - void RewriteLifetimeIntrinsic(IntrinsicInst *II, AllocaInst *AI, - uint64_t Offset, - SmallVectorImpl<AllocaInst *> &NewElts); - void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, - AllocaInst *AI, - SmallVectorImpl<AllocaInst *> &NewElts); - void RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI, - SmallVectorImpl<AllocaInst *> &NewElts); - void RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI, - SmallVectorImpl<AllocaInst *> &NewElts); - bool ShouldAttemptScalarRepl(AllocaInst *AI); - }; - - // SROA_DT - SROA that uses DominatorTree. - struct SROA_DT : public SROA { - static char ID; - public: - SROA_DT(int T = -1, int ST = -1, int AT = -1, int SLT = -1) : - SROA(T, true, ID, ST, AT, SLT) { - initializeSROA_DTPass(*PassRegistry::getPassRegistry()); - } - - // getAnalysisUsage - This pass does not require any passes, but we know it - // will not alter the CFG, so say so. - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<AssumptionCacheTracker>(); - AU.addRequired<DominatorTreeWrapperPass>(); - AU.setPreservesCFG(); - } - }; - - // SROA_SSAUp - SROA that uses SSAUpdater. - struct SROA_SSAUp : public SROA { - static char ID; - public: - SROA_SSAUp(int T = -1, int ST = -1, int AT = -1, int SLT = -1) : - SROA(T, false, ID, ST, AT, SLT) { - initializeSROA_SSAUpPass(*PassRegistry::getPassRegistry()); - } - - // getAnalysisUsage - This pass does not require any passes, but we know it - // will not alter the CFG, so say so. - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<AssumptionCacheTracker>(); - AU.setPreservesCFG(); - } - }; - -} - -char SROA_DT::ID = 0; -char SROA_SSAUp::ID = 0; - -INITIALIZE_PASS_BEGIN(SROA_DT, "scalarrepl", - "Scalar Replacement of Aggregates (DT)", false, false) -INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) -INITIALIZE_PASS_END(SROA_DT, "scalarrepl", - "Scalar Replacement of Aggregates (DT)", false, false) - -INITIALIZE_PASS_BEGIN(SROA_SSAUp, "scalarrepl-ssa", - "Scalar Replacement of Aggregates (SSAUp)", false, false) -INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) -INITIALIZE_PASS_END(SROA_SSAUp, "scalarrepl-ssa", - "Scalar Replacement of Aggregates (SSAUp)", false, false) - -// Public interface to the ScalarReplAggregates pass -FunctionPass *llvm::createScalarReplAggregatesPass(int Threshold, - bool UseDomTree, - int StructMemberThreshold, - int ArrayElementThreshold, - int ScalarLoadThreshold) { - if (UseDomTree) - return new SROA_DT(Threshold, StructMemberThreshold, ArrayElementThreshold, - ScalarLoadThreshold); - return new SROA_SSAUp(Threshold, StructMemberThreshold, - ArrayElementThreshold, ScalarLoadThreshold); -} - - -//===----------------------------------------------------------------------===// -// Convert To Scalar Optimization. -//===----------------------------------------------------------------------===// - -namespace { -/// ConvertToScalarInfo - This class implements the "Convert To Scalar" -/// optimization, which scans the uses of an alloca and determines if it can -/// rewrite it in terms of a single new alloca that can be mem2reg'd. -class ConvertToScalarInfo { - /// AllocaSize - The size of the alloca being considered in bytes. - unsigned AllocaSize; - const DataLayout &DL; - unsigned ScalarLoadThreshold; - - /// IsNotTrivial - This is set to true if there is some access to the object - /// which means that mem2reg can't promote it. - bool IsNotTrivial; - - /// ScalarKind - Tracks the kind of alloca being considered for promotion, - /// computed based on the uses of the alloca rather than the LLVM type system. - enum { - Unknown, - - // Accesses via GEPs that are consistent with element access of a vector - // type. This will not be converted into a vector unless there is a later - // access using an actual vector type. - ImplicitVector, - - // Accesses via vector operations and GEPs that are consistent with the - // layout of a vector type. - Vector, - - // An integer bag-of-bits with bitwise operations for insertion and - // extraction. Any combination of types can be converted into this kind - // of scalar. - Integer - } ScalarKind; - - /// VectorTy - This tracks the type that we should promote the vector to if - /// it is possible to turn it into a vector. This starts out null, and if it - /// isn't possible to turn into a vector type, it gets set to VoidTy. - VectorType *VectorTy; - - /// HadNonMemTransferAccess - True if there is at least one access to the - /// alloca that is not a MemTransferInst. We don't want to turn structs into - /// large integers unless there is some potential for optimization. - bool HadNonMemTransferAccess; - - /// HadDynamicAccess - True if some element of this alloca was dynamic. - /// We don't yet have support for turning a dynamic access into a large - /// integer. - bool HadDynamicAccess; - -public: - explicit ConvertToScalarInfo(unsigned Size, const DataLayout &DL, - unsigned SLT) - : AllocaSize(Size), DL(DL), ScalarLoadThreshold(SLT), IsNotTrivial(false), - ScalarKind(Unknown), VectorTy(nullptr), HadNonMemTransferAccess(false), - HadDynamicAccess(false) { } - - AllocaInst *TryConvert(AllocaInst *AI); - -private: - bool CanConvertToScalar(Value *V, uint64_t Offset, Value* NonConstantIdx); - void MergeInTypeForLoadOrStore(Type *In, uint64_t Offset); - bool MergeInVectorType(VectorType *VInTy, uint64_t Offset); - void ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset, - Value *NonConstantIdx); - - Value *ConvertScalar_ExtractValue(Value *NV, Type *ToType, - uint64_t Offset, Value* NonConstantIdx, - IRBuilder<> &Builder); - Value *ConvertScalar_InsertValue(Value *StoredVal, Value *ExistingVal, - uint64_t Offset, Value* NonConstantIdx, - IRBuilder<> &Builder); -}; -} // end anonymous namespace. - - -/// TryConvert - Analyze the specified alloca, and if it is safe to do so, -/// rewrite it to be a new alloca which is mem2reg'able. This returns the new -/// alloca if possible or null if not. -AllocaInst *ConvertToScalarInfo::TryConvert(AllocaInst *AI) { - // If we can't convert this scalar, or if mem2reg can trivially do it, bail - // out. - if (!CanConvertToScalar(AI, 0, nullptr) || !IsNotTrivial) - return nullptr; - - // If an alloca has only memset / memcpy uses, it may still have an Unknown - // ScalarKind. Treat it as an Integer below. - if (ScalarKind == Unknown) - ScalarKind = Integer; - - if (ScalarKind == Vector && VectorTy->getBitWidth() != AllocaSize * 8) - ScalarKind = Integer; - - // If we were able to find a vector type that can handle this with - // insert/extract elements, and if there was at least one use that had - // a vector type, promote this to a vector. We don't want to promote - // random stuff that doesn't use vectors (e.g. <9 x double>) because then - // we just get a lot of insert/extracts. If at least one vector is - // involved, then we probably really do have a union of vector/array. - Type *NewTy; - if (ScalarKind == Vector) { - assert(VectorTy && "Missing type for vector scalar."); - DEBUG(dbgs() << "CONVERT TO VECTOR: " << *AI << "\n TYPE = " - << *VectorTy << '\n'); - NewTy = VectorTy; // Use the vector type. - } else { - unsigned BitWidth = AllocaSize * 8; - - // Do not convert to scalar integer if the alloca size exceeds the - // scalar load threshold. - if (BitWidth > ScalarLoadThreshold) - return nullptr; - - if ((ScalarKind == ImplicitVector || ScalarKind == Integer) && - !HadNonMemTransferAccess && !DL.fitsInLegalInteger(BitWidth)) - return nullptr; - // Dynamic accesses on integers aren't yet supported. They need us to shift - // by a dynamic amount which could be difficult to work out as we might not - // know whether to use a left or right shift. - if (ScalarKind == Integer && HadDynamicAccess) - return nullptr; - - DEBUG(dbgs() << "CONVERT TO SCALAR INTEGER: " << *AI << "\n"); - // Create and insert the integer alloca. - NewTy = IntegerType::get(AI->getContext(), BitWidth); - } - AllocaInst *NewAI = - new AllocaInst(NewTy, nullptr, "", &AI->getParent()->front()); - ConvertUsesToScalar(AI, NewAI, 0, nullptr); - return NewAI; -} - -/// MergeInTypeForLoadOrStore - Add the 'In' type to the accumulated vector type -/// (VectorTy) so far at the offset specified by Offset (which is specified in -/// bytes). -/// -/// There are two cases we handle here: -/// 1) A union of vector types of the same size and potentially its elements. -/// Here we turn element accesses into insert/extract element operations. -/// This promotes a <4 x float> with a store of float to the third element -/// into a <4 x float> that uses insert element. -/// 2) A fully general blob of memory, which we turn into some (potentially -/// large) integer type with extract and insert operations where the loads -/// and stores would mutate the memory. We mark this by setting VectorTy -/// to VoidTy. -void ConvertToScalarInfo::MergeInTypeForLoadOrStore(Type *In, - uint64_t Offset) { - // If we already decided to turn this into a blob of integer memory, there is - // nothing to be done. - if (ScalarKind == Integer) - return; - - // If this could be contributing to a vector, analyze it. - - // If the In type is a vector that is the same size as the alloca, see if it - // matches the existing VecTy. - if (VectorType *VInTy = dyn_cast<VectorType>(In)) { - if (MergeInVectorType(VInTy, Offset)) - return; - } else if (In->isFloatTy() || In->isDoubleTy() || - (In->isIntegerTy() && In->getPrimitiveSizeInBits() >= 8 && - isPowerOf2_32(In->getPrimitiveSizeInBits()))) { - // Full width accesses can be ignored, because they can always be turned - // into bitcasts. - unsigned EltSize = In->getPrimitiveSizeInBits()/8; - if (EltSize == AllocaSize) - return; - - // If we're accessing something that could be an element of a vector, see - // if the implied vector agrees with what we already have and if Offset is - // compatible with it. - if (Offset % EltSize == 0 && AllocaSize % EltSize == 0 && - (!VectorTy || EltSize == VectorTy->getElementType() - ->getPrimitiveSizeInBits()/8)) { - if (!VectorTy) { - ScalarKind = ImplicitVector; - VectorTy = VectorType::get(In, AllocaSize/EltSize); - } - return; - } - } - - // Otherwise, we have a case that we can't handle with an optimized vector - // form. We can still turn this into a large integer. - ScalarKind = Integer; -} - -/// MergeInVectorType - Handles the vector case of MergeInTypeForLoadOrStore, -/// returning true if the type was successfully merged and false otherwise. -bool ConvertToScalarInfo::MergeInVectorType(VectorType *VInTy, - uint64_t Offset) { - if (VInTy->getBitWidth()/8 == AllocaSize && Offset == 0) { - // If we're storing/loading a vector of the right size, allow it as a - // vector. If this the first vector we see, remember the type so that - // we know the element size. If this is a subsequent access, ignore it - // even if it is a differing type but the same size. Worst case we can - // bitcast the resultant vectors. - if (!VectorTy) - VectorTy = VInTy; - ScalarKind = Vector; - return true; - } - - return false; -} - -/// CanConvertToScalar - V is a pointer. If we can convert the pointee and all -/// its accesses to a single vector type, return true and set VecTy to -/// the new type. If we could convert the alloca into a single promotable -/// integer, return true but set VecTy to VoidTy. Further, if the use is not a -/// completely trivial use that mem2reg could promote, set IsNotTrivial. Offset -/// is the current offset from the base of the alloca being analyzed. -/// -/// If we see at least one access to the value that is as a vector type, set the -/// SawVec flag. -bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset, - Value* NonConstantIdx) { - for (User *U : V->users()) { - Instruction *UI = cast<Instruction>(U); - - if (LoadInst *LI = dyn_cast<LoadInst>(UI)) { - // Don't break volatile loads. - if (!LI->isSimple()) - return false; - // Don't touch MMX operations. - if (LI->getType()->isX86_MMXTy()) - return false; - HadNonMemTransferAccess = true; - MergeInTypeForLoadOrStore(LI->getType(), Offset); - continue; - } - - if (StoreInst *SI = dyn_cast<StoreInst>(UI)) { - // Storing the pointer, not into the value? - if (SI->getOperand(0) == V || !SI->isSimple()) return false; - // Don't touch MMX operations. - if (SI->getOperand(0)->getType()->isX86_MMXTy()) - return false; - HadNonMemTransferAccess = true; - MergeInTypeForLoadOrStore(SI->getOperand(0)->getType(), Offset); - continue; - } - - if (BitCastInst *BCI = dyn_cast<BitCastInst>(UI)) { - if (!onlyUsedByLifetimeMarkers(BCI)) - IsNotTrivial = true; // Can't be mem2reg'd. - if (!CanConvertToScalar(BCI, Offset, NonConstantIdx)) - return false; - continue; - } - - if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(UI)) { - // If this is a GEP with a variable indices, we can't handle it. - PointerType* PtrTy = dyn_cast<PointerType>(GEP->getPointerOperandType()); - if (!PtrTy) - return false; - - // Compute the offset that this GEP adds to the pointer. - SmallVector<Value*, 8> Indices(GEP->op_begin()+1, GEP->op_end()); - Value *GEPNonConstantIdx = nullptr; - if (!GEP->hasAllConstantIndices()) { - if (!isa<VectorType>(PtrTy->getElementType())) - return false; - if (NonConstantIdx) - return false; - GEPNonConstantIdx = Indices.pop_back_val(); - if (!GEPNonConstantIdx->getType()->isIntegerTy(32)) - return false; - HadDynamicAccess = true; - } else - GEPNonConstantIdx = NonConstantIdx; - uint64_t GEPOffset = DL.getIndexedOffset(PtrTy, - Indices); - // See if all uses can be converted. - if (!CanConvertToScalar(GEP, Offset+GEPOffset, GEPNonConstantIdx)) - return false; - IsNotTrivial = true; // Can't be mem2reg'd. - HadNonMemTransferAccess = true; - continue; - } - - // If this is a constant sized memset of a constant value (e.g. 0) we can - // handle it. - if (MemSetInst *MSI = dyn_cast<MemSetInst>(UI)) { - // Store to dynamic index. - if (NonConstantIdx) - return false; - // Store of constant value. - if (!isa<ConstantInt>(MSI->getValue())) - return false; - - // Store of constant size. - ConstantInt *Len = dyn_cast<ConstantInt>(MSI->getLength()); - if (!Len) - return false; - - // If the size differs from the alloca, we can only convert the alloca to - // an integer bag-of-bits. - // FIXME: This should handle all of the cases that are currently accepted - // as vector element insertions. - if (Len->getZExtValue() != AllocaSize || Offset != 0) - ScalarKind = Integer; - - IsNotTrivial = true; // Can't be mem2reg'd. - HadNonMemTransferAccess = true; - continue; - } - - // If this is a memcpy or memmove into or out of the whole allocation, we - // can handle it like a load or store of the scalar type. - if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(UI)) { - // Store to dynamic index. - if (NonConstantIdx) - return false; - ConstantInt *Len = dyn_cast<ConstantInt>(MTI->getLength()); - if (!Len || Len->getZExtValue() != AllocaSize || Offset != 0) - return false; - - IsNotTrivial = true; // Can't be mem2reg'd. - continue; - } - - // If this is a lifetime intrinsic, we can handle it. - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(UI)) { - if (II->getIntrinsicID() == Intrinsic::lifetime_start || - II->getIntrinsicID() == Intrinsic::lifetime_end) { - continue; - } - } - - // Otherwise, we cannot handle this! - return false; - } - - return true; -} - -/// ConvertUsesToScalar - Convert all of the users of Ptr to use the new alloca -/// directly. This happens when we are converting an "integer union" to a -/// single integer scalar, or when we are converting a "vector union" to a -/// vector with insert/extractelement instructions. -/// -/// Offset is an offset from the original alloca, in bits that need to be -/// shifted to the right. By the end of this, there should be no uses of Ptr. -void ConvertToScalarInfo::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, - uint64_t Offset, - Value* NonConstantIdx) { - while (!Ptr->use_empty()) { - Instruction *User = cast<Instruction>(Ptr->user_back()); - - if (BitCastInst *CI = dyn_cast<BitCastInst>(User)) { - ConvertUsesToScalar(CI, NewAI, Offset, NonConstantIdx); - CI->eraseFromParent(); - continue; - } - - if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) { - // Compute the offset that this GEP adds to the pointer. - SmallVector<Value*, 8> Indices(GEP->op_begin()+1, GEP->op_end()); - Value* GEPNonConstantIdx = nullptr; - if (!GEP->hasAllConstantIndices()) { - assert(!NonConstantIdx && - "Dynamic GEP reading from dynamic GEP unsupported"); - GEPNonConstantIdx = Indices.pop_back_val(); - } else - GEPNonConstantIdx = NonConstantIdx; - uint64_t GEPOffset = DL.getIndexedOffset(GEP->getPointerOperandType(), - Indices); - ConvertUsesToScalar(GEP, NewAI, Offset+GEPOffset*8, GEPNonConstantIdx); - GEP->eraseFromParent(); - continue; - } - - IRBuilder<> Builder(User); - - if (LoadInst *LI = dyn_cast<LoadInst>(User)) { - // The load is a bit extract from NewAI shifted right by Offset bits. - Value *LoadedVal = Builder.CreateLoad(NewAI); - Value *NewLoadVal - = ConvertScalar_ExtractValue(LoadedVal, LI->getType(), Offset, - NonConstantIdx, Builder); - LI->replaceAllUsesWith(NewLoadVal); - LI->eraseFromParent(); - continue; - } - - if (StoreInst *SI = dyn_cast<StoreInst>(User)) { - assert(SI->getOperand(0) != Ptr && "Consistency error!"); - Instruction *Old = Builder.CreateLoad(NewAI, NewAI->getName()+".in"); - Value *New = ConvertScalar_InsertValue(SI->getOperand(0), Old, Offset, - NonConstantIdx, Builder); - Builder.CreateStore(New, NewAI); - SI->eraseFromParent(); - - // If the load we just inserted is now dead, then the inserted store - // overwrote the entire thing. - if (Old->use_empty()) - Old->eraseFromParent(); - continue; - } - - // If this is a constant sized memset of a constant value (e.g. 0) we can - // transform it into a store of the expanded constant value. - if (MemSetInst *MSI = dyn_cast<MemSetInst>(User)) { - assert(MSI->getRawDest() == Ptr && "Consistency error!"); - assert(!NonConstantIdx && "Cannot replace dynamic memset with insert"); - int64_t SNumBytes = cast<ConstantInt>(MSI->getLength())->getSExtValue(); - if (SNumBytes > 0 && (SNumBytes >> 32) == 0) { - unsigned NumBytes = static_cast<unsigned>(SNumBytes); - unsigned Val = cast<ConstantInt>(MSI->getValue())->getZExtValue(); - - // Compute the value replicated the right number of times. - APInt APVal(NumBytes*8, Val); - - // Splat the value if non-zero. - if (Val) - for (unsigned i = 1; i != NumBytes; ++i) - APVal |= APVal << 8; - - Instruction *Old = Builder.CreateLoad(NewAI, NewAI->getName()+".in"); - Value *New = ConvertScalar_InsertValue( - ConstantInt::get(User->getContext(), APVal), - Old, Offset, nullptr, Builder); - Builder.CreateStore(New, NewAI); - - // If the load we just inserted is now dead, then the memset overwrote - // the entire thing. - if (Old->use_empty()) - Old->eraseFromParent(); - } - MSI->eraseFromParent(); - continue; - } - - // If this is a memcpy or memmove into or out of the whole allocation, we - // can handle it like a load or store of the scalar type. - if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(User)) { - assert(Offset == 0 && "must be store to start of alloca"); - assert(!NonConstantIdx && "Cannot replace dynamic transfer with insert"); - - // If the source and destination are both to the same alloca, then this is - // a noop copy-to-self, just delete it. Otherwise, emit a load and store - // as appropriate. - AllocaInst *OrigAI = cast<AllocaInst>(GetUnderlyingObject(Ptr, DL, 0)); - - if (GetUnderlyingObject(MTI->getSource(), DL, 0) != OrigAI) { - // Dest must be OrigAI, change this to be a load from the original - // pointer (bitcasted), then a store to our new alloca. - assert(MTI->getRawDest() == Ptr && "Neither use is of pointer?"); - Value *SrcPtr = MTI->getSource(); - PointerType* SPTy = cast<PointerType>(SrcPtr->getType()); - PointerType* AIPTy = cast<PointerType>(NewAI->getType()); - if (SPTy->getAddressSpace() != AIPTy->getAddressSpace()) { - AIPTy = PointerType::get(AIPTy->getElementType(), - SPTy->getAddressSpace()); - } - SrcPtr = Builder.CreateBitCast(SrcPtr, AIPTy); - - LoadInst *SrcVal = Builder.CreateLoad(SrcPtr, "srcval"); - SrcVal->setAlignment(MTI->getAlignment()); - Builder.CreateStore(SrcVal, NewAI); - } else if (GetUnderlyingObject(MTI->getDest(), DL, 0) != OrigAI) { - // Src must be OrigAI, change this to be a load from NewAI then a store - // through the original dest pointer (bitcasted). - assert(MTI->getRawSource() == Ptr && "Neither use is of pointer?"); - LoadInst *SrcVal = Builder.CreateLoad(NewAI, "srcval"); - - PointerType* DPTy = cast<PointerType>(MTI->getDest()->getType()); - PointerType* AIPTy = cast<PointerType>(NewAI->getType()); - if (DPTy->getAddressSpace() != AIPTy->getAddressSpace()) { - AIPTy = PointerType::get(AIPTy->getElementType(), - DPTy->getAddressSpace()); - } - Value *DstPtr = Builder.CreateBitCast(MTI->getDest(), AIPTy); - - StoreInst *NewStore = Builder.CreateStore(SrcVal, DstPtr); - NewStore->setAlignment(MTI->getAlignment()); - } else { - // Noop transfer. Src == Dst - } - - MTI->eraseFromParent(); - continue; - } - - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(User)) { - if (II->getIntrinsicID() == Intrinsic::lifetime_start || - II->getIntrinsicID() == Intrinsic::lifetime_end) { - // There's no need to preserve these, as the resulting alloca will be - // converted to a register anyways. - II->eraseFromParent(); - continue; - } - } - - llvm_unreachable("Unsupported operation!"); - } -} - -/// ConvertScalar_ExtractValue - Extract a value of type ToType from an integer -/// or vector value FromVal, extracting the bits from the offset specified by -/// Offset. This returns the value, which is of type ToType. -/// -/// This happens when we are converting an "integer union" to a single -/// integer scalar, or when we are converting a "vector union" to a vector with -/// insert/extractelement instructions. -/// -/// Offset is an offset from the original alloca, in bits that need to be -/// shifted to the right. -Value *ConvertToScalarInfo:: -ConvertScalar_ExtractValue(Value *FromVal, Type *ToType, - uint64_t Offset, Value* NonConstantIdx, - IRBuilder<> &Builder) { - // If the load is of the whole new alloca, no conversion is needed. - Type *FromType = FromVal->getType(); - if (FromType == ToType && Offset == 0) - return FromVal; - - // If the result alloca is a vector type, this is either an element - // access or a bitcast to another vector type of the same size. - if (VectorType *VTy = dyn_cast<VectorType>(FromType)) { - unsigned FromTypeSize = DL.getTypeAllocSize(FromType); - unsigned ToTypeSize = DL.getTypeAllocSize(ToType); - if (FromTypeSize == ToTypeSize) - return Builder.CreateBitCast(FromVal, ToType); - - // Otherwise it must be an element access. - unsigned Elt = 0; - if (Offset) { - unsigned EltSize = DL.getTypeAllocSizeInBits(VTy->getElementType()); - Elt = Offset/EltSize; - assert(EltSize*Elt == Offset && "Invalid modulus in validity checking"); - } - // Return the element extracted out of it. - Value *Idx; - if (NonConstantIdx) { - if (Elt) - Idx = Builder.CreateAdd(NonConstantIdx, - Builder.getInt32(Elt), - "dyn.offset"); - else - Idx = NonConstantIdx; - } else - Idx = Builder.getInt32(Elt); - Value *V = Builder.CreateExtractElement(FromVal, Idx); - if (V->getType() != ToType) - V = Builder.CreateBitCast(V, ToType); - return V; - } - - // If ToType is a first class aggregate, extract out each of the pieces and - // use insertvalue's to form the FCA. - if (StructType *ST = dyn_cast<StructType>(ToType)) { - assert(!NonConstantIdx && - "Dynamic indexing into struct types not supported"); - const StructLayout &Layout = *DL.getStructLayout(ST); - Value *Res = UndefValue::get(ST); - for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { - Value *Elt = ConvertScalar_ExtractValue(FromVal, ST->getElementType(i), - Offset+Layout.getElementOffsetInBits(i), - nullptr, Builder); - Res = Builder.CreateInsertValue(Res, Elt, i); - } - return Res; - } - - if (ArrayType *AT = dyn_cast<ArrayType>(ToType)) { - assert(!NonConstantIdx && - "Dynamic indexing into array types not supported"); - uint64_t EltSize = DL.getTypeAllocSizeInBits(AT->getElementType()); - Value *Res = UndefValue::get(AT); - for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { - Value *Elt = ConvertScalar_ExtractValue(FromVal, AT->getElementType(), - Offset+i*EltSize, nullptr, - Builder); - Res = Builder.CreateInsertValue(Res, Elt, i); - } - return Res; - } - - // Otherwise, this must be a union that was converted to an integer value. - IntegerType *NTy = cast<IntegerType>(FromVal->getType()); - - // If this is a big-endian system and the load is narrower than the - // full alloca type, we need to do a shift to get the right bits. - int ShAmt = 0; - if (DL.isBigEndian()) { - // On big-endian machines, the lowest bit is stored at the bit offset - // from the pointer given by getTypeStoreSizeInBits. This matters for - // integers with a bitwidth that is not a multiple of 8. - ShAmt = DL.getTypeStoreSizeInBits(NTy) - - DL.getTypeStoreSizeInBits(ToType) - Offset; - } else { - ShAmt = Offset; - } - - // Note: we support negative bitwidths (with shl) which are not defined. - // We do this to support (f.e.) loads off the end of a structure where - // only some bits are used. - if (ShAmt > 0 && (unsigned)ShAmt < NTy->getBitWidth()) - FromVal = Builder.CreateLShr(FromVal, - ConstantInt::get(FromVal->getType(), ShAmt)); - else if (ShAmt < 0 && (unsigned)-ShAmt < NTy->getBitWidth()) - FromVal = Builder.CreateShl(FromVal, - ConstantInt::get(FromVal->getType(), -ShAmt)); - - // Finally, unconditionally truncate the integer to the right width. - unsigned LIBitWidth = DL.getTypeSizeInBits(ToType); - if (LIBitWidth < NTy->getBitWidth()) - FromVal = - Builder.CreateTrunc(FromVal, IntegerType::get(FromVal->getContext(), - LIBitWidth)); - else if (LIBitWidth > NTy->getBitWidth()) - FromVal = - Builder.CreateZExt(FromVal, IntegerType::get(FromVal->getContext(), - LIBitWidth)); - - // If the result is an integer, this is a trunc or bitcast. - if (ToType->isIntegerTy()) { - // Should be done. - } else if (ToType->isFloatingPointTy() || ToType->isVectorTy()) { - // Just do a bitcast, we know the sizes match up. - FromVal = Builder.CreateBitCast(FromVal, ToType); - } else { - // Otherwise must be a pointer. - FromVal = Builder.CreateIntToPtr(FromVal, ToType); - } - assert(FromVal->getType() == ToType && "Didn't convert right?"); - return FromVal; -} - -/// ConvertScalar_InsertValue - Insert the value "SV" into the existing integer -/// or vector value "Old" at the offset specified by Offset. -/// -/// This happens when we are converting an "integer union" to a -/// single integer scalar, or when we are converting a "vector union" to a -/// vector with insert/extractelement instructions. -/// -/// Offset is an offset from the original alloca, in bits that need to be -/// shifted to the right. -/// -/// NonConstantIdx is an index value if there was a GEP with a non-constant -/// index value. If this is 0 then all GEPs used to find this insert address -/// are constant. -Value *ConvertToScalarInfo:: -ConvertScalar_InsertValue(Value *SV, Value *Old, - uint64_t Offset, Value* NonConstantIdx, - IRBuilder<> &Builder) { - // Convert the stored type to the actual type, shift it left to insert - // then 'or' into place. - Type *AllocaType = Old->getType(); - LLVMContext &Context = Old->getContext(); - - if (VectorType *VTy = dyn_cast<VectorType>(AllocaType)) { - uint64_t VecSize = DL.getTypeAllocSizeInBits(VTy); - uint64_t ValSize = DL.getTypeAllocSizeInBits(SV->getType()); - - // Changing the whole vector with memset or with an access of a different - // vector type? - if (ValSize == VecSize) - return Builder.CreateBitCast(SV, AllocaType); - - // Must be an element insertion. - Type *EltTy = VTy->getElementType(); - if (SV->getType() != EltTy) - SV = Builder.CreateBitCast(SV, EltTy); - uint64_t EltSize = DL.getTypeAllocSizeInBits(EltTy); - unsigned Elt = Offset/EltSize; - Value *Idx; - if (NonConstantIdx) { - if (Elt) - Idx = Builder.CreateAdd(NonConstantIdx, - Builder.getInt32(Elt), - "dyn.offset"); - else - Idx = NonConstantIdx; - } else - Idx = Builder.getInt32(Elt); - return Builder.CreateInsertElement(Old, SV, Idx); - } - - // If SV is a first-class aggregate value, insert each value recursively. - if (StructType *ST = dyn_cast<StructType>(SV->getType())) { - assert(!NonConstantIdx && - "Dynamic indexing into struct types not supported"); - const StructLayout &Layout = *DL.getStructLayout(ST); - for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { - Value *Elt = Builder.CreateExtractValue(SV, i); - Old = ConvertScalar_InsertValue(Elt, Old, - Offset+Layout.getElementOffsetInBits(i), - nullptr, Builder); - } - return Old; - } - - if (ArrayType *AT = dyn_cast<ArrayType>(SV->getType())) { - assert(!NonConstantIdx && - "Dynamic indexing into array types not supported"); - uint64_t EltSize = DL.getTypeAllocSizeInBits(AT->getElementType()); - for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { - Value *Elt = Builder.CreateExtractValue(SV, i); - Old = ConvertScalar_InsertValue(Elt, Old, Offset+i*EltSize, nullptr, - Builder); - } - return Old; - } - - // If SV is a float, convert it to the appropriate integer type. - // If it is a pointer, do the same. - unsigned SrcWidth = DL.getTypeSizeInBits(SV->getType()); - unsigned DestWidth = DL.getTypeSizeInBits(AllocaType); - unsigned SrcStoreWidth = DL.getTypeStoreSizeInBits(SV->getType()); - unsigned DestStoreWidth = DL.getTypeStoreSizeInBits(AllocaType); - if (SV->getType()->isFloatingPointTy() || SV->getType()->isVectorTy()) - SV = Builder.CreateBitCast(SV, IntegerType::get(SV->getContext(),SrcWidth)); - else if (SV->getType()->isPointerTy()) - SV = Builder.CreatePtrToInt(SV, DL.getIntPtrType(SV->getType())); - - // Zero extend or truncate the value if needed. - if (SV->getType() != AllocaType) { - if (SV->getType()->getPrimitiveSizeInBits() < - AllocaType->getPrimitiveSizeInBits()) - SV = Builder.CreateZExt(SV, AllocaType); - else { - // Truncation may be needed if storing more than the alloca can hold - // (undefined behavior). - SV = Builder.CreateTrunc(SV, AllocaType); - SrcWidth = DestWidth; - SrcStoreWidth = DestStoreWidth; - } - } - - // If this is a big-endian system and the store is narrower than the - // full alloca type, we need to do a shift to get the right bits. - int ShAmt = 0; - if (DL.isBigEndian()) { - // On big-endian machines, the lowest bit is stored at the bit offset - // from the pointer given by getTypeStoreSizeInBits. This matters for - // integers with a bitwidth that is not a multiple of 8. - ShAmt = DestStoreWidth - SrcStoreWidth - Offset; - } else { - ShAmt = Offset; - } - - // Note: we support negative bitwidths (with shr) which are not defined. - // We do this to support (f.e.) stores off the end of a structure where - // only some bits in the structure are set. - APInt Mask(APInt::getLowBitsSet(DestWidth, SrcWidth)); - if (ShAmt > 0 && (unsigned)ShAmt < DestWidth) { - SV = Builder.CreateShl(SV, ConstantInt::get(SV->getType(), ShAmt)); - Mask <<= ShAmt; - } else if (ShAmt < 0 && (unsigned)-ShAmt < DestWidth) { - SV = Builder.CreateLShr(SV, ConstantInt::get(SV->getType(), -ShAmt)); - Mask = Mask.lshr(-ShAmt); - } - - // Mask out the bits we are about to insert from the old value, and or - // in the new bits. - if (SrcWidth != DestWidth) { - assert(DestWidth > SrcWidth); - Old = Builder.CreateAnd(Old, ConstantInt::get(Context, ~Mask), "mask"); - SV = Builder.CreateOr(Old, SV, "ins"); - } - return SV; -} - - -//===----------------------------------------------------------------------===// -// SRoA Driver -//===----------------------------------------------------------------------===// - - -bool SROA::runOnFunction(Function &F) { - if (skipOptnoneFunction(F)) - return false; - - bool Changed = performPromotion(F); - - while (1) { - bool LocalChange = performScalarRepl(F); - if (!LocalChange) break; // No need to repromote if no scalarrepl - Changed = true; - LocalChange = performPromotion(F); - if (!LocalChange) break; // No need to re-scalarrepl if no promotion - } - - return Changed; -} - -namespace { -class AllocaPromoter : public LoadAndStorePromoter { - AllocaInst *AI; - DIBuilder *DIB; - SmallVector<DbgDeclareInst *, 4> DDIs; - SmallVector<DbgValueInst *, 4> DVIs; -public: - AllocaPromoter(ArrayRef<Instruction*> Insts, SSAUpdater &S, - DIBuilder *DB) - : LoadAndStorePromoter(Insts, S), AI(nullptr), DIB(DB) {} - - void run(AllocaInst *AI, const SmallVectorImpl<Instruction*> &Insts) { - // Remember which alloca we're promoting (for isInstInList). - this->AI = AI; - if (auto *L = LocalAsMetadata::getIfExists(AI)) { - if (auto *DINode = MetadataAsValue::getIfExists(AI->getContext(), L)) { - for (User *U : DINode->users()) - if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(U)) - DDIs.push_back(DDI); - else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(U)) - DVIs.push_back(DVI); - } - } - - LoadAndStorePromoter::run(Insts); - AI->eraseFromParent(); - for (SmallVectorImpl<DbgDeclareInst *>::iterator I = DDIs.begin(), - E = DDIs.end(); I != E; ++I) { - DbgDeclareInst *DDI = *I; - DDI->eraseFromParent(); - } - for (SmallVectorImpl<DbgValueInst *>::iterator I = DVIs.begin(), - E = DVIs.end(); I != E; ++I) { - DbgValueInst *DVI = *I; - DVI->eraseFromParent(); - } - } - - bool isInstInList(Instruction *I, - const SmallVectorImpl<Instruction*> &Insts) const override { - if (LoadInst *LI = dyn_cast<LoadInst>(I)) - return LI->getOperand(0) == AI; - return cast<StoreInst>(I)->getPointerOperand() == AI; - } - - void updateDebugInfo(Instruction *Inst) const override { - for (SmallVectorImpl<DbgDeclareInst *>::const_iterator I = DDIs.begin(), - E = DDIs.end(); I != E; ++I) { - DbgDeclareInst *DDI = *I; - if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) - ConvertDebugDeclareToDebugValue(DDI, SI, *DIB); - else if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) - ConvertDebugDeclareToDebugValue(DDI, LI, *DIB); - } - for (SmallVectorImpl<DbgValueInst *>::const_iterator I = DVIs.begin(), - E = DVIs.end(); I != E; ++I) { - DbgValueInst *DVI = *I; - Value *Arg = nullptr; - if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { - // If an argument is zero extended then use argument directly. The ZExt - // may be zapped by an optimization pass in future. - if (ZExtInst *ZExt = dyn_cast<ZExtInst>(SI->getOperand(0))) - Arg = dyn_cast<Argument>(ZExt->getOperand(0)); - if (SExtInst *SExt = dyn_cast<SExtInst>(SI->getOperand(0))) - Arg = dyn_cast<Argument>(SExt->getOperand(0)); - if (!Arg) - Arg = SI->getOperand(0); - } else if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) { - Arg = LI->getOperand(0); - } else { - continue; - } - DIB->insertDbgValueIntrinsic(Arg, 0, DVI->getVariable(), - DVI->getExpression(), DVI->getDebugLoc(), - Inst); - } - } -}; -} // end anon namespace - -/// isSafeSelectToSpeculate - Select instructions that use an alloca and are -/// subsequently loaded can be rewritten to load both input pointers and then -/// select between the result, allowing the load of the alloca to be promoted. -/// From this: -/// %P2 = select i1 %cond, i32* %Alloca, i32* %Other -/// %V = load i32* %P2 -/// to: -/// %V1 = load i32* %Alloca -> will be mem2reg'd -/// %V2 = load i32* %Other -/// %V = select i1 %cond, i32 %V1, i32 %V2 -/// -/// We can do this to a select if its only uses are loads and if the operand to -/// the select can be loaded unconditionally. -static bool isSafeSelectToSpeculate(SelectInst *SI) { - const DataLayout &DL = SI->getModule()->getDataLayout(); - bool TDerefable = isDereferenceablePointer(SI->getTrueValue(), DL); - bool FDerefable = isDereferenceablePointer(SI->getFalseValue(), DL); - - for (User *U : SI->users()) { - LoadInst *LI = dyn_cast<LoadInst>(U); - if (!LI || !LI->isSimple()) return false; - - // Both operands to the select need to be dereferencable, either absolutely - // (e.g. allocas) or at this point because we can see other accesses to it. - if (!TDerefable && - !isSafeToLoadUnconditionally(SI->getTrueValue(), LI, - LI->getAlignment())) - return false; - if (!FDerefable && - !isSafeToLoadUnconditionally(SI->getFalseValue(), LI, - LI->getAlignment())) - return false; - } - - return true; -} - -/// isSafePHIToSpeculate - PHI instructions that use an alloca and are -/// subsequently loaded can be rewritten to load both input pointers in the pred -/// blocks and then PHI the results, allowing the load of the alloca to be -/// promoted. -/// From this: -/// %P2 = phi [i32* %Alloca, i32* %Other] -/// %V = load i32* %P2 -/// to: -/// %V1 = load i32* %Alloca -> will be mem2reg'd -/// ... -/// %V2 = load i32* %Other -/// ... -/// %V = phi [i32 %V1, i32 %V2] -/// -/// We can do this to a select if its only uses are loads and if the operand to -/// the select can be loaded unconditionally. -static bool isSafePHIToSpeculate(PHINode *PN) { - // For now, we can only do this promotion if the load is in the same block as - // the PHI, and if there are no stores between the phi and load. - // TODO: Allow recursive phi users. - // TODO: Allow stores. - BasicBlock *BB = PN->getParent(); - unsigned MaxAlign = 0; - for (User *U : PN->users()) { - LoadInst *LI = dyn_cast<LoadInst>(U); - if (!LI || !LI->isSimple()) return false; - - // For now we only allow loads in the same block as the PHI. This is a - // common case that happens when instcombine merges two loads through a PHI. - if (LI->getParent() != BB) return false; - - // Ensure that there are no instructions between the PHI and the load that - // could store. - for (BasicBlock::iterator BBI(PN); &*BBI != LI; ++BBI) - if (BBI->mayWriteToMemory()) - return false; - - MaxAlign = std::max(MaxAlign, LI->getAlignment()); - } - - const DataLayout &DL = PN->getModule()->getDataLayout(); - - // Okay, we know that we have one or more loads in the same block as the PHI. - // We can transform this if it is safe to push the loads into the predecessor - // blocks. The only thing to watch out for is that we can't put a possibly - // trapping load in the predecessor if it is a critical edge. - for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { - BasicBlock *Pred = PN->getIncomingBlock(i); - Value *InVal = PN->getIncomingValue(i); - - // If the terminator of the predecessor has side-effects (an invoke), - // there is no safe place to put a load in the predecessor. - if (Pred->getTerminator()->mayHaveSideEffects()) - return false; - - // If the value is produced by the terminator of the predecessor - // (an invoke), there is no valid place to put a load in the predecessor. - if (Pred->getTerminator() == InVal) - return false; - - // If the predecessor has a single successor, then the edge isn't critical. - if (Pred->getTerminator()->getNumSuccessors() == 1) - continue; - - // If this pointer is always safe to load, or if we can prove that there is - // already a load in the block, then we can move the load to the pred block. - if (isDereferenceablePointer(InVal, DL) || - isSafeToLoadUnconditionally(InVal, Pred->getTerminator(), MaxAlign)) - continue; - - return false; - } - - return true; -} - - -/// tryToMakeAllocaBePromotable - This returns true if the alloca only has -/// direct (non-volatile) loads and stores to it. If the alloca is close but -/// not quite there, this will transform the code to allow promotion. As such, -/// it is a non-pure predicate. -static bool tryToMakeAllocaBePromotable(AllocaInst *AI, const DataLayout &DL) { - SetVector<Instruction*, SmallVector<Instruction*, 4>, - SmallPtrSet<Instruction*, 4> > InstsToRewrite; - for (User *U : AI->users()) { - if (LoadInst *LI = dyn_cast<LoadInst>(U)) { - if (!LI->isSimple()) - return false; - continue; - } - - if (StoreInst *SI = dyn_cast<StoreInst>(U)) { - if (SI->getOperand(0) == AI || !SI->isSimple()) - return false; // Don't allow a store OF the AI, only INTO the AI. - continue; - } - - if (SelectInst *SI = dyn_cast<SelectInst>(U)) { - // If the condition being selected on is a constant, fold the select, yes - // this does (rarely) happen early on. - if (ConstantInt *CI = dyn_cast<ConstantInt>(SI->getCondition())) { - Value *Result = SI->getOperand(1+CI->isZero()); - SI->replaceAllUsesWith(Result); - SI->eraseFromParent(); - - // This is very rare and we just scrambled the use list of AI, start - // over completely. - return tryToMakeAllocaBePromotable(AI, DL); - } - - // If it is safe to turn "load (select c, AI, ptr)" into a select of two - // loads, then we can transform this by rewriting the select. - if (!isSafeSelectToSpeculate(SI)) - return false; - - InstsToRewrite.insert(SI); - continue; - } - - if (PHINode *PN = dyn_cast<PHINode>(U)) { - if (PN->use_empty()) { // Dead PHIs can be stripped. - InstsToRewrite.insert(PN); - continue; - } - - // If it is safe to turn "load (phi [AI, ptr, ...])" into a PHI of loads - // in the pred blocks, then we can transform this by rewriting the PHI. - if (!isSafePHIToSpeculate(PN)) - return false; - - InstsToRewrite.insert(PN); - continue; - } - - if (BitCastInst *BCI = dyn_cast<BitCastInst>(U)) { - if (onlyUsedByLifetimeMarkers(BCI)) { - InstsToRewrite.insert(BCI); - continue; - } - } - - return false; - } - - // If there are no instructions to rewrite, then all uses are load/stores and - // we're done! - if (InstsToRewrite.empty()) - return true; - - // If we have instructions that need to be rewritten for this to be promotable - // take care of it now. - for (unsigned i = 0, e = InstsToRewrite.size(); i != e; ++i) { - if (BitCastInst *BCI = dyn_cast<BitCastInst>(InstsToRewrite[i])) { - // This could only be a bitcast used by nothing but lifetime intrinsics. - for (BitCastInst::user_iterator I = BCI->user_begin(), E = BCI->user_end(); - I != E;) - cast<Instruction>(*I++)->eraseFromParent(); - BCI->eraseFromParent(); - continue; - } - - if (SelectInst *SI = dyn_cast<SelectInst>(InstsToRewrite[i])) { - // Selects in InstsToRewrite only have load uses. Rewrite each as two - // loads with a new select. - while (!SI->use_empty()) { - LoadInst *LI = cast<LoadInst>(SI->user_back()); - - IRBuilder<> Builder(LI); - LoadInst *TrueLoad = - Builder.CreateLoad(SI->getTrueValue(), LI->getName()+".t"); - LoadInst *FalseLoad = - Builder.CreateLoad(SI->getFalseValue(), LI->getName()+".f"); - - // Transfer alignment and AA info if present. - TrueLoad->setAlignment(LI->getAlignment()); - FalseLoad->setAlignment(LI->getAlignment()); - - AAMDNodes Tags; - LI->getAAMetadata(Tags); - if (Tags) { - TrueLoad->setAAMetadata(Tags); - FalseLoad->setAAMetadata(Tags); - } - - Value *V = Builder.CreateSelect(SI->getCondition(), TrueLoad, FalseLoad); - V->takeName(LI); - LI->replaceAllUsesWith(V); - LI->eraseFromParent(); - } - - // Now that all the loads are gone, the select is gone too. - SI->eraseFromParent(); - continue; - } - - // Otherwise, we have a PHI node which allows us to push the loads into the - // predecessors. - PHINode *PN = cast<PHINode>(InstsToRewrite[i]); - if (PN->use_empty()) { - PN->eraseFromParent(); - continue; - } - - Type *LoadTy = cast<PointerType>(PN->getType())->getElementType(); - PHINode *NewPN = PHINode::Create(LoadTy, PN->getNumIncomingValues(), - PN->getName()+".ld", PN); - - // Get the AA tags and alignment to use from one of the loads. It doesn't - // matter which one we get and if any differ, it doesn't matter. - LoadInst *SomeLoad = cast<LoadInst>(PN->user_back()); - - AAMDNodes AATags; - SomeLoad->getAAMetadata(AATags); - unsigned Align = SomeLoad->getAlignment(); - - // Rewrite all loads of the PN to use the new PHI. - while (!PN->use_empty()) { - LoadInst *LI = cast<LoadInst>(PN->user_back()); - LI->replaceAllUsesWith(NewPN); - LI->eraseFromParent(); - } - - // Inject loads into all of the pred blocks. Keep track of which blocks we - // insert them into in case we have multiple edges from the same block. - DenseMap<BasicBlock*, LoadInst*> InsertedLoads; - - for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { - BasicBlock *Pred = PN->getIncomingBlock(i); - LoadInst *&Load = InsertedLoads[Pred]; - if (!Load) { - Load = new LoadInst(PN->getIncomingValue(i), - PN->getName() + "." + Pred->getName(), - Pred->getTerminator()); - Load->setAlignment(Align); - if (AATags) Load->setAAMetadata(AATags); - } - - NewPN->addIncoming(Load, Pred); - } - - PN->eraseFromParent(); - } - - ++NumAdjusted; - return true; -} - -bool SROA::performPromotion(Function &F) { - std::vector<AllocaInst*> Allocas; - const DataLayout &DL = F.getParent()->getDataLayout(); - DominatorTree *DT = nullptr; - if (HasDomTree) - DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - AssumptionCache &AC = - getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); - - BasicBlock &BB = F.getEntryBlock(); // Get the entry node for the function - DIBuilder DIB(*F.getParent(), /*AllowUnresolved*/ false); - bool Changed = false; - SmallVector<Instruction*, 64> Insts; - while (1) { - Allocas.clear(); - - // Find allocas that are safe to promote, by looking at all instructions in - // the entry node - for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) - if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) // Is it an alloca? - if (tryToMakeAllocaBePromotable(AI, DL)) - Allocas.push_back(AI); - - if (Allocas.empty()) break; - - if (HasDomTree) - PromoteMemToReg(Allocas, *DT, nullptr, &AC); - else { - SSAUpdater SSA; - for (unsigned i = 0, e = Allocas.size(); i != e; ++i) { - AllocaInst *AI = Allocas[i]; - - // Build list of instructions to promote. - for (User *U : AI->users()) - Insts.push_back(cast<Instruction>(U)); - AllocaPromoter(Insts, SSA, &DIB).run(AI, Insts); - Insts.clear(); - } - } - NumPromoted += Allocas.size(); - Changed = true; - } - - return Changed; -} - - -/// ShouldAttemptScalarRepl - Decide if an alloca is a good candidate for -/// SROA. It must be a struct or array type with a small number of elements. -bool SROA::ShouldAttemptScalarRepl(AllocaInst *AI) { - Type *T = AI->getAllocatedType(); - // Do not promote any struct that has too many members. - if (StructType *ST = dyn_cast<StructType>(T)) - return ST->getNumElements() <= StructMemberThreshold; - // Do not promote any array that has too many elements. - if (ArrayType *AT = dyn_cast<ArrayType>(T)) - return AT->getNumElements() <= ArrayElementThreshold; - return false; -} - -// performScalarRepl - This algorithm is a simple worklist driven algorithm, -// which runs on all of the alloca instructions in the entry block, removing -// them if they are only used by getelementptr instructions. -// -bool SROA::performScalarRepl(Function &F) { - std::vector<AllocaInst*> WorkList; - const DataLayout &DL = F.getParent()->getDataLayout(); - - // Scan the entry basic block, adding allocas to the worklist. - BasicBlock &BB = F.getEntryBlock(); - for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) - if (AllocaInst *A = dyn_cast<AllocaInst>(I)) - WorkList.push_back(A); - - // Process the worklist - bool Changed = false; - while (!WorkList.empty()) { - AllocaInst *AI = WorkList.back(); - WorkList.pop_back(); - - // Handle dead allocas trivially. These can be formed by SROA'ing arrays - // with unused elements. - if (AI->use_empty()) { - AI->eraseFromParent(); - Changed = true; - continue; - } - - // If this alloca is impossible for us to promote, reject it early. - if (AI->isArrayAllocation() || !AI->getAllocatedType()->isSized()) - continue; - - // Check to see if we can perform the core SROA transformation. We cannot - // transform the allocation instruction if it is an array allocation - // (allocations OF arrays are ok though), and an allocation of a scalar - // value cannot be decomposed at all. - uint64_t AllocaSize = DL.getTypeAllocSize(AI->getAllocatedType()); - - // Do not promote [0 x %struct]. - if (AllocaSize == 0) continue; - - // Do not promote any struct whose size is too big. - if (AllocaSize > SRThreshold) continue; - - // If the alloca looks like a good candidate for scalar replacement, and if - // all its users can be transformed, then split up the aggregate into its - // separate elements. - if (ShouldAttemptScalarRepl(AI) && isSafeAllocaToScalarRepl(AI)) { - DoScalarReplacement(AI, WorkList); - Changed = true; - continue; - } - - // If we can turn this aggregate value (potentially with casts) into a - // simple scalar value that can be mem2reg'd into a register value. - // IsNotTrivial tracks whether this is something that mem2reg could have - // promoted itself. If so, we don't want to transform it needlessly. Note - // that we can't just check based on the type: the alloca may be of an i32 - // but that has pointer arithmetic to set byte 3 of it or something. - if (AllocaInst *NewAI = - ConvertToScalarInfo((unsigned)AllocaSize, DL, ScalarLoadThreshold) - .TryConvert(AI)) { - NewAI->takeName(AI); - AI->eraseFromParent(); - ++NumConverted; - Changed = true; - continue; - } - - // Otherwise, couldn't process this alloca. - } - - return Changed; -} - -/// DoScalarReplacement - This alloca satisfied the isSafeAllocaToScalarRepl -/// predicate, do SROA now. -void SROA::DoScalarReplacement(AllocaInst *AI, - std::vector<AllocaInst*> &WorkList) { - DEBUG(dbgs() << "Found inst to SROA: " << *AI << '\n'); - SmallVector<AllocaInst*, 32> ElementAllocas; - if (StructType *ST = dyn_cast<StructType>(AI->getAllocatedType())) { - ElementAllocas.reserve(ST->getNumContainedTypes()); - for (unsigned i = 0, e = ST->getNumContainedTypes(); i != e; ++i) { - AllocaInst *NA = new AllocaInst(ST->getContainedType(i), nullptr, - AI->getAlignment(), - AI->getName() + "." + Twine(i), AI); - ElementAllocas.push_back(NA); - WorkList.push_back(NA); // Add to worklist for recursive processing - } - } else { - ArrayType *AT = cast<ArrayType>(AI->getAllocatedType()); - ElementAllocas.reserve(AT->getNumElements()); - Type *ElTy = AT->getElementType(); - for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { - AllocaInst *NA = new AllocaInst(ElTy, nullptr, AI->getAlignment(), - AI->getName() + "." + Twine(i), AI); - ElementAllocas.push_back(NA); - WorkList.push_back(NA); // Add to worklist for recursive processing - } - } - - // Now that we have created the new alloca instructions, rewrite all the - // uses of the old alloca. - RewriteForScalarRepl(AI, AI, 0, ElementAllocas); - - // Now erase any instructions that were made dead while rewriting the alloca. - DeleteDeadInstructions(); - AI->eraseFromParent(); - - ++NumReplaced; -} - -/// DeleteDeadInstructions - Erase instructions on the DeadInstrs list, -/// recursively including all their operands that become trivially dead. -void SROA::DeleteDeadInstructions() { - while (!DeadInsts.empty()) { - Instruction *I = cast<Instruction>(DeadInsts.pop_back_val()); - - for (User::op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) - if (Instruction *U = dyn_cast<Instruction>(*OI)) { - // Zero out the operand and see if it becomes trivially dead. - // (But, don't add allocas to the dead instruction list -- they are - // already on the worklist and will be deleted separately.) - *OI = nullptr; - if (isInstructionTriviallyDead(U) && !isa<AllocaInst>(U)) - DeadInsts.push_back(U); - } - - I->eraseFromParent(); - } -} - -/// isSafeForScalarRepl - Check if instruction I is a safe use with regard to -/// performing scalar replacement of alloca AI. The results are flagged in -/// the Info parameter. Offset indicates the position within AI that is -/// referenced by this instruction. -void SROA::isSafeForScalarRepl(Instruction *I, uint64_t Offset, - AllocaInfo &Info) { - const DataLayout &DL = I->getModule()->getDataLayout(); - for (Use &U : I->uses()) { - Instruction *User = cast<Instruction>(U.getUser()); - - if (BitCastInst *BC = dyn_cast<BitCastInst>(User)) { - isSafeForScalarRepl(BC, Offset, Info); - } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) { - uint64_t GEPOffset = Offset; - isSafeGEP(GEPI, GEPOffset, Info); - if (!Info.isUnsafe) - isSafeForScalarRepl(GEPI, GEPOffset, Info); - } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(User)) { - ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength()); - if (!Length || Length->isNegative()) - return MarkUnsafe(Info, User); - - isSafeMemAccess(Offset, Length->getZExtValue(), nullptr, - U.getOperandNo() == 0, Info, MI, - true /*AllowWholeAccess*/); - } else if (LoadInst *LI = dyn_cast<LoadInst>(User)) { - if (!LI->isSimple()) - return MarkUnsafe(Info, User); - Type *LIType = LI->getType(); - isSafeMemAccess(Offset, DL.getTypeAllocSize(LIType), LIType, false, Info, - LI, true /*AllowWholeAccess*/); - Info.hasALoadOrStore = true; - - } else if (StoreInst *SI = dyn_cast<StoreInst>(User)) { - // Store is ok if storing INTO the pointer, not storing the pointer - if (!SI->isSimple() || SI->getOperand(0) == I) - return MarkUnsafe(Info, User); - - Type *SIType = SI->getOperand(0)->getType(); - isSafeMemAccess(Offset, DL.getTypeAllocSize(SIType), SIType, true, Info, - SI, true /*AllowWholeAccess*/); - Info.hasALoadOrStore = true; - } else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(User)) { - if (II->getIntrinsicID() != Intrinsic::lifetime_start && - II->getIntrinsicID() != Intrinsic::lifetime_end) - return MarkUnsafe(Info, User); - } else if (isa<PHINode>(User) || isa<SelectInst>(User)) { - isSafePHISelectUseForScalarRepl(User, Offset, Info); - } else { - return MarkUnsafe(Info, User); - } - if (Info.isUnsafe) return; - } -} - - -/// isSafePHIUseForScalarRepl - If we see a PHI node or select using a pointer -/// derived from the alloca, we can often still split the alloca into elements. -/// This is useful if we have a large alloca where one element is phi'd -/// together somewhere: we can SRoA and promote all the other elements even if -/// we end up not being able to promote this one. -/// -/// All we require is that the uses of the PHI do not index into other parts of -/// the alloca. The most important use case for this is single load and stores -/// that are PHI'd together, which can happen due to code sinking. -void SROA::isSafePHISelectUseForScalarRepl(Instruction *I, uint64_t Offset, - AllocaInfo &Info) { - // If we've already checked this PHI, don't do it again. - if (PHINode *PN = dyn_cast<PHINode>(I)) - if (!Info.CheckedPHIs.insert(PN).second) - return; - - const DataLayout &DL = I->getModule()->getDataLayout(); - for (User *U : I->users()) { - Instruction *UI = cast<Instruction>(U); - - if (BitCastInst *BC = dyn_cast<BitCastInst>(UI)) { - isSafePHISelectUseForScalarRepl(BC, Offset, Info); - } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(UI)) { - // Only allow "bitcast" GEPs for simplicity. We could generalize this, - // but would have to prove that we're staying inside of an element being - // promoted. - if (!GEPI->hasAllZeroIndices()) - return MarkUnsafe(Info, UI); - isSafePHISelectUseForScalarRepl(GEPI, Offset, Info); - } else if (LoadInst *LI = dyn_cast<LoadInst>(UI)) { - if (!LI->isSimple()) - return MarkUnsafe(Info, UI); - Type *LIType = LI->getType(); - isSafeMemAccess(Offset, DL.getTypeAllocSize(LIType), LIType, false, Info, - LI, false /*AllowWholeAccess*/); - Info.hasALoadOrStore = true; - - } else if (StoreInst *SI = dyn_cast<StoreInst>(UI)) { - // Store is ok if storing INTO the pointer, not storing the pointer - if (!SI->isSimple() || SI->getOperand(0) == I) - return MarkUnsafe(Info, UI); - - Type *SIType = SI->getOperand(0)->getType(); - isSafeMemAccess(Offset, DL.getTypeAllocSize(SIType), SIType, true, Info, - SI, false /*AllowWholeAccess*/); - Info.hasALoadOrStore = true; - } else if (isa<PHINode>(UI) || isa<SelectInst>(UI)) { - isSafePHISelectUseForScalarRepl(UI, Offset, Info); - } else { - return MarkUnsafe(Info, UI); - } - if (Info.isUnsafe) return; - } -} - -/// isSafeGEP - Check if a GEP instruction can be handled for scalar -/// replacement. It is safe when all the indices are constant, in-bounds -/// references, and when the resulting offset corresponds to an element within -/// the alloca type. The results are flagged in the Info parameter. Upon -/// return, Offset is adjusted as specified by the GEP indices. -void SROA::isSafeGEP(GetElementPtrInst *GEPI, - uint64_t &Offset, AllocaInfo &Info) { - gep_type_iterator GEPIt = gep_type_begin(GEPI), E = gep_type_end(GEPI); - if (GEPIt == E) - return; - bool NonConstant = false; - unsigned NonConstantIdxSize = 0; - - // Walk through the GEP type indices, checking the types that this indexes - // into. - for (; GEPIt != E; ++GEPIt) { - // Ignore struct elements, no extra checking needed for these. - if ((*GEPIt)->isStructTy()) - continue; - - ConstantInt *IdxVal = dyn_cast<ConstantInt>(GEPIt.getOperand()); - if (!IdxVal) - return MarkUnsafe(Info, GEPI); - } - - // Compute the offset due to this GEP and check if the alloca has a - // component element at that offset. - SmallVector<Value*, 8> Indices(GEPI->op_begin() + 1, GEPI->op_end()); - // If this GEP is non-constant then the last operand must have been a - // dynamic index into a vector. Pop this now as it has no impact on the - // constant part of the offset. - if (NonConstant) - Indices.pop_back(); - - const DataLayout &DL = GEPI->getModule()->getDataLayout(); - Offset += DL.getIndexedOffset(GEPI->getPointerOperandType(), Indices); - if (!TypeHasComponent(Info.AI->getAllocatedType(), Offset, NonConstantIdxSize, - DL)) - MarkUnsafe(Info, GEPI); -} - -/// isHomogeneousAggregate - Check if type T is a struct or array containing -/// elements of the same type (which is always true for arrays). If so, -/// return true with NumElts and EltTy set to the number of elements and the -/// element type, respectively. -static bool isHomogeneousAggregate(Type *T, unsigned &NumElts, - Type *&EltTy) { - if (ArrayType *AT = dyn_cast<ArrayType>(T)) { - NumElts = AT->getNumElements(); - EltTy = (NumElts == 0 ? nullptr : AT->getElementType()); - return true; - } - if (StructType *ST = dyn_cast<StructType>(T)) { - NumElts = ST->getNumContainedTypes(); - EltTy = (NumElts == 0 ? nullptr : ST->getContainedType(0)); - for (unsigned n = 1; n < NumElts; ++n) { - if (ST->getContainedType(n) != EltTy) - return false; - } - return true; - } - return false; -} - -/// isCompatibleAggregate - Check if T1 and T2 are either the same type or are -/// "homogeneous" aggregates with the same element type and number of elements. -static bool isCompatibleAggregate(Type *T1, Type *T2) { - if (T1 == T2) - return true; - - unsigned NumElts1, NumElts2; - Type *EltTy1, *EltTy2; - if (isHomogeneousAggregate(T1, NumElts1, EltTy1) && - isHomogeneousAggregate(T2, NumElts2, EltTy2) && - NumElts1 == NumElts2 && - EltTy1 == EltTy2) - return true; - - return false; -} - -/// isSafeMemAccess - Check if a load/store/memcpy operates on the entire AI -/// alloca or has an offset and size that corresponds to a component element -/// within it. The offset checked here may have been formed from a GEP with a -/// pointer bitcasted to a different type. -/// -/// If AllowWholeAccess is true, then this allows uses of the entire alloca as a -/// unit. If false, it only allows accesses known to be in a single element. -void SROA::isSafeMemAccess(uint64_t Offset, uint64_t MemSize, - Type *MemOpType, bool isStore, - AllocaInfo &Info, Instruction *TheAccess, - bool AllowWholeAccess) { - const DataLayout &DL = TheAccess->getModule()->getDataLayout(); - // Check if this is a load/store of the entire alloca. - if (Offset == 0 && AllowWholeAccess && - MemSize == DL.getTypeAllocSize(Info.AI->getAllocatedType())) { - // This can be safe for MemIntrinsics (where MemOpType is 0) and integer - // loads/stores (which are essentially the same as the MemIntrinsics with - // regard to copying padding between elements). But, if an alloca is - // flagged as both a source and destination of such operations, we'll need - // to check later for padding between elements. - if (!MemOpType || MemOpType->isIntegerTy()) { - if (isStore) - Info.isMemCpyDst = true; - else - Info.isMemCpySrc = true; - return; - } - // This is also safe for references using a type that is compatible with - // the type of the alloca, so that loads/stores can be rewritten using - // insertvalue/extractvalue. - if (isCompatibleAggregate(MemOpType, Info.AI->getAllocatedType())) { - Info.hasSubelementAccess = true; - return; - } - } - // Check if the offset/size correspond to a component within the alloca type. - Type *T = Info.AI->getAllocatedType(); - if (TypeHasComponent(T, Offset, MemSize, DL)) { - Info.hasSubelementAccess = true; - return; - } - - return MarkUnsafe(Info, TheAccess); -} - -/// TypeHasComponent - Return true if T has a component type with the -/// specified offset and size. If Size is zero, do not check the size. -bool SROA::TypeHasComponent(Type *T, uint64_t Offset, uint64_t Size, - const DataLayout &DL) { - Type *EltTy; - uint64_t EltSize; - if (StructType *ST = dyn_cast<StructType>(T)) { - const StructLayout *Layout = DL.getStructLayout(ST); - unsigned EltIdx = Layout->getElementContainingOffset(Offset); - EltTy = ST->getContainedType(EltIdx); - EltSize = DL.getTypeAllocSize(EltTy); - Offset -= Layout->getElementOffset(EltIdx); - } else if (ArrayType *AT = dyn_cast<ArrayType>(T)) { - EltTy = AT->getElementType(); - EltSize = DL.getTypeAllocSize(EltTy); - if (Offset >= AT->getNumElements() * EltSize) - return false; - Offset %= EltSize; - } else if (VectorType *VT = dyn_cast<VectorType>(T)) { - EltTy = VT->getElementType(); - EltSize = DL.getTypeAllocSize(EltTy); - if (Offset >= VT->getNumElements() * EltSize) - return false; - Offset %= EltSize; - } else { - return false; - } - if (Offset == 0 && (Size == 0 || EltSize == Size)) - return true; - // Check if the component spans multiple elements. - if (Offset + Size > EltSize) - return false; - return TypeHasComponent(EltTy, Offset, Size, DL); -} - -/// RewriteForScalarRepl - Alloca AI is being split into NewElts, so rewrite -/// the instruction I, which references it, to use the separate elements. -/// Offset indicates the position within AI that is referenced by this -/// instruction. -void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, - SmallVectorImpl<AllocaInst *> &NewElts) { - const DataLayout &DL = I->getModule()->getDataLayout(); - for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI!=E;) { - Use &TheUse = *UI++; - Instruction *User = cast<Instruction>(TheUse.getUser()); - - if (BitCastInst *BC = dyn_cast<BitCastInst>(User)) { - RewriteBitCast(BC, AI, Offset, NewElts); - continue; - } - - if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) { - RewriteGEP(GEPI, AI, Offset, NewElts); - continue; - } - - if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(User)) { - ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength()); - uint64_t MemSize = Length->getZExtValue(); - if (Offset == 0 && MemSize == DL.getTypeAllocSize(AI->getAllocatedType())) - RewriteMemIntrinUserOfAlloca(MI, I, AI, NewElts); - // Otherwise the intrinsic can only touch a single element and the - // address operand will be updated, so nothing else needs to be done. - continue; - } - - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(User)) { - if (II->getIntrinsicID() == Intrinsic::lifetime_start || - II->getIntrinsicID() == Intrinsic::lifetime_end) { - RewriteLifetimeIntrinsic(II, AI, Offset, NewElts); - } - continue; - } - - if (LoadInst *LI = dyn_cast<LoadInst>(User)) { - Type *LIType = LI->getType(); - - if (isCompatibleAggregate(LIType, AI->getAllocatedType())) { - // Replace: - // %res = load { i32, i32 }* %alloc - // with: - // %load.0 = load i32* %alloc.0 - // %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 - // %load.1 = load i32* %alloc.1 - // %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 - // (Also works for arrays instead of structs) - Value *Insert = UndefValue::get(LIType); - IRBuilder<> Builder(LI); - for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { - Value *Load = Builder.CreateLoad(NewElts[i], "load"); - Insert = Builder.CreateInsertValue(Insert, Load, i, "insert"); - } - LI->replaceAllUsesWith(Insert); - DeadInsts.push_back(LI); - } else if (LIType->isIntegerTy() && - DL.getTypeAllocSize(LIType) == - DL.getTypeAllocSize(AI->getAllocatedType())) { - // If this is a load of the entire alloca to an integer, rewrite it. - RewriteLoadUserOfWholeAlloca(LI, AI, NewElts); - } - continue; - } - - if (StoreInst *SI = dyn_cast<StoreInst>(User)) { - Value *Val = SI->getOperand(0); - Type *SIType = Val->getType(); - if (isCompatibleAggregate(SIType, AI->getAllocatedType())) { - // Replace: - // store { i32, i32 } %val, { i32, i32 }* %alloc - // with: - // %val.0 = extractvalue { i32, i32 } %val, 0 - // store i32 %val.0, i32* %alloc.0 - // %val.1 = extractvalue { i32, i32 } %val, 1 - // store i32 %val.1, i32* %alloc.1 - // (Also works for arrays instead of structs) - IRBuilder<> Builder(SI); - for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { - Value *Extract = Builder.CreateExtractValue(Val, i, Val->getName()); - Builder.CreateStore(Extract, NewElts[i]); - } - DeadInsts.push_back(SI); - } else if (SIType->isIntegerTy() && - DL.getTypeAllocSize(SIType) == - DL.getTypeAllocSize(AI->getAllocatedType())) { - // If this is a store of the entire alloca from an integer, rewrite it. - RewriteStoreUserOfWholeAlloca(SI, AI, NewElts); - } - continue; - } - - if (isa<SelectInst>(User) || isa<PHINode>(User)) { - // If we have a PHI user of the alloca itself (as opposed to a GEP or - // bitcast) we have to rewrite it. GEP and bitcast uses will be RAUW'd to - // the new pointer. - if (!isa<AllocaInst>(I)) continue; - - assert(Offset == 0 && NewElts[0] && - "Direct alloca use should have a zero offset"); - - // If we have a use of the alloca, we know the derived uses will be - // utilizing just the first element of the scalarized result. Insert a - // bitcast of the first alloca before the user as required. - AllocaInst *NewAI = NewElts[0]; - BitCastInst *BCI = new BitCastInst(NewAI, AI->getType(), "", NewAI); - NewAI->moveBefore(BCI); - TheUse = BCI; - continue; - } - } -} - -/// RewriteBitCast - Update a bitcast reference to the alloca being replaced -/// and recursively continue updating all of its uses. -void SROA::RewriteBitCast(BitCastInst *BC, AllocaInst *AI, uint64_t Offset, - SmallVectorImpl<AllocaInst *> &NewElts) { - RewriteForScalarRepl(BC, AI, Offset, NewElts); - if (BC->getOperand(0) != AI) - return; - - // The bitcast references the original alloca. Replace its uses with - // references to the alloca containing offset zero (which is normally at - // index zero, but might not be in cases involving structs with elements - // of size zero). - Type *T = AI->getAllocatedType(); - uint64_t EltOffset = 0; - Type *IdxTy; - uint64_t Idx = FindElementAndOffset(T, EltOffset, IdxTy, - BC->getModule()->getDataLayout()); - Instruction *Val = NewElts[Idx]; - if (Val->getType() != BC->getDestTy()) { - Val = new BitCastInst(Val, BC->getDestTy(), "", BC); - Val->takeName(BC); - } - BC->replaceAllUsesWith(Val); - DeadInsts.push_back(BC); -} - -/// FindElementAndOffset - Return the index of the element containing Offset -/// within the specified type, which must be either a struct or an array. -/// Sets T to the type of the element and Offset to the offset within that -/// element. IdxTy is set to the type of the index result to be used in a -/// GEP instruction. -uint64_t SROA::FindElementAndOffset(Type *&T, uint64_t &Offset, Type *&IdxTy, - const DataLayout &DL) { - uint64_t Idx = 0; - - if (StructType *ST = dyn_cast<StructType>(T)) { - const StructLayout *Layout = DL.getStructLayout(ST); - Idx = Layout->getElementContainingOffset(Offset); - T = ST->getContainedType(Idx); - Offset -= Layout->getElementOffset(Idx); - IdxTy = Type::getInt32Ty(T->getContext()); - return Idx; - } else if (ArrayType *AT = dyn_cast<ArrayType>(T)) { - T = AT->getElementType(); - uint64_t EltSize = DL.getTypeAllocSize(T); - Idx = Offset / EltSize; - Offset -= Idx * EltSize; - IdxTy = Type::getInt64Ty(T->getContext()); - return Idx; - } - VectorType *VT = cast<VectorType>(T); - T = VT->getElementType(); - uint64_t EltSize = DL.getTypeAllocSize(T); - Idx = Offset / EltSize; - Offset -= Idx * EltSize; - IdxTy = Type::getInt64Ty(T->getContext()); - return Idx; -} - -/// RewriteGEP - Check if this GEP instruction moves the pointer across -/// elements of the alloca that are being split apart, and if so, rewrite -/// the GEP to be relative to the new element. -void SROA::RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset, - SmallVectorImpl<AllocaInst *> &NewElts) { - uint64_t OldOffset = Offset; - const DataLayout &DL = GEPI->getModule()->getDataLayout(); - SmallVector<Value*, 8> Indices(GEPI->op_begin() + 1, GEPI->op_end()); - // If the GEP was dynamic then it must have been a dynamic vector lookup. - // In this case, it must be the last GEP operand which is dynamic so keep that - // aside until we've found the constant GEP offset then add it back in at the - // end. - Value* NonConstantIdx = nullptr; - if (!GEPI->hasAllConstantIndices()) - NonConstantIdx = Indices.pop_back_val(); - Offset += DL.getIndexedOffset(GEPI->getPointerOperandType(), Indices); - - RewriteForScalarRepl(GEPI, AI, Offset, NewElts); - - Type *T = AI->getAllocatedType(); - Type *IdxTy; - uint64_t OldIdx = FindElementAndOffset(T, OldOffset, IdxTy, DL); - if (GEPI->getOperand(0) == AI) - OldIdx = ~0ULL; // Force the GEP to be rewritten. - - T = AI->getAllocatedType(); - uint64_t EltOffset = Offset; - uint64_t Idx = FindElementAndOffset(T, EltOffset, IdxTy, DL); - - // If this GEP does not move the pointer across elements of the alloca - // being split, then it does not needs to be rewritten. - if (Idx == OldIdx) - return; - - Type *i32Ty = Type::getInt32Ty(AI->getContext()); - SmallVector<Value*, 8> NewArgs; - NewArgs.push_back(Constant::getNullValue(i32Ty)); - while (EltOffset != 0) { - uint64_t EltIdx = FindElementAndOffset(T, EltOffset, IdxTy, DL); - NewArgs.push_back(ConstantInt::get(IdxTy, EltIdx)); - } - if (NonConstantIdx) { - Type* GepTy = T; - // This GEP has a dynamic index. We need to add "i32 0" to index through - // any structs or arrays in the original type until we get to the vector - // to index. - while (!isa<VectorType>(GepTy)) { - NewArgs.push_back(Constant::getNullValue(i32Ty)); - GepTy = cast<CompositeType>(GepTy)->getTypeAtIndex(0U); - } - NewArgs.push_back(NonConstantIdx); - } - Instruction *Val = NewElts[Idx]; - if (NewArgs.size() > 1) { - Val = GetElementPtrInst::CreateInBounds(Val, NewArgs, "", GEPI); - Val->takeName(GEPI); - } - if (Val->getType() != GEPI->getType()) - Val = new BitCastInst(Val, GEPI->getType(), Val->getName(), GEPI); - GEPI->replaceAllUsesWith(Val); - DeadInsts.push_back(GEPI); -} - -/// RewriteLifetimeIntrinsic - II is a lifetime.start/lifetime.end. Rewrite it -/// to mark the lifetime of the scalarized memory. -void SROA::RewriteLifetimeIntrinsic(IntrinsicInst *II, AllocaInst *AI, - uint64_t Offset, - SmallVectorImpl<AllocaInst *> &NewElts) { - ConstantInt *OldSize = cast<ConstantInt>(II->getArgOperand(0)); - // Put matching lifetime markers on everything from Offset up to - // Offset+OldSize. - Type *AIType = AI->getAllocatedType(); - const DataLayout &DL = II->getModule()->getDataLayout(); - uint64_t NewOffset = Offset; - Type *IdxTy; - uint64_t Idx = FindElementAndOffset(AIType, NewOffset, IdxTy, DL); - - IRBuilder<> Builder(II); - uint64_t Size = OldSize->getLimitedValue(); - - if (NewOffset) { - // Splice the first element and index 'NewOffset' bytes in. SROA will - // split the alloca again later. - unsigned AS = AI->getType()->getAddressSpace(); - Value *V = Builder.CreateBitCast(NewElts[Idx], Builder.getInt8PtrTy(AS)); - V = Builder.CreateGEP(Builder.getInt8Ty(), V, Builder.getInt64(NewOffset)); - - IdxTy = NewElts[Idx]->getAllocatedType(); - uint64_t EltSize = DL.getTypeAllocSize(IdxTy) - NewOffset; - if (EltSize > Size) { - EltSize = Size; - Size = 0; - } else { - Size -= EltSize; - } - if (II->getIntrinsicID() == Intrinsic::lifetime_start) - Builder.CreateLifetimeStart(V, Builder.getInt64(EltSize)); - else - Builder.CreateLifetimeEnd(V, Builder.getInt64(EltSize)); - ++Idx; - } - - for (; Idx != NewElts.size() && Size; ++Idx) { - IdxTy = NewElts[Idx]->getAllocatedType(); - uint64_t EltSize = DL.getTypeAllocSize(IdxTy); - if (EltSize > Size) { - EltSize = Size; - Size = 0; - } else { - Size -= EltSize; - } - if (II->getIntrinsicID() == Intrinsic::lifetime_start) - Builder.CreateLifetimeStart(NewElts[Idx], - Builder.getInt64(EltSize)); - else - Builder.CreateLifetimeEnd(NewElts[Idx], - Builder.getInt64(EltSize)); - } - DeadInsts.push_back(II); -} - -/// RewriteMemIntrinUserOfAlloca - MI is a memcpy/memset/memmove from or to AI. -/// Rewrite it to copy or set the elements of the scalarized memory. -void -SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, - AllocaInst *AI, - SmallVectorImpl<AllocaInst *> &NewElts) { - // If this is a memcpy/memmove, construct the other pointer as the - // appropriate type. The "Other" pointer is the pointer that goes to memory - // that doesn't have anything to do with the alloca that we are promoting. For - // memset, this Value* stays null. - Value *OtherPtr = nullptr; - unsigned MemAlignment = MI->getAlignment(); - if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) { // memmove/memcopy - if (Inst == MTI->getRawDest()) - OtherPtr = MTI->getRawSource(); - else { - assert(Inst == MTI->getRawSource()); - OtherPtr = MTI->getRawDest(); - } - } - - // If there is an other pointer, we want to convert it to the same pointer - // type as AI has, so we can GEP through it safely. - if (OtherPtr) { - unsigned AddrSpace = - cast<PointerType>(OtherPtr->getType())->getAddressSpace(); - - // Remove bitcasts and all-zero GEPs from OtherPtr. This is an - // optimization, but it's also required to detect the corner case where - // both pointer operands are referencing the same memory, and where - // OtherPtr may be a bitcast or GEP that currently being rewritten. (This - // function is only called for mem intrinsics that access the whole - // aggregate, so non-zero GEPs are not an issue here.) - OtherPtr = OtherPtr->stripPointerCasts(); - - // Copying the alloca to itself is a no-op: just delete it. - if (OtherPtr == AI || OtherPtr == NewElts[0]) { - // This code will run twice for a no-op memcpy -- once for each operand. - // Put only one reference to MI on the DeadInsts list. - for (SmallVectorImpl<Value *>::const_iterator I = DeadInsts.begin(), - E = DeadInsts.end(); I != E; ++I) - if (*I == MI) return; - DeadInsts.push_back(MI); - return; - } - - // If the pointer is not the right type, insert a bitcast to the right - // type. - Type *NewTy = - PointerType::get(AI->getType()->getElementType(), AddrSpace); - - if (OtherPtr->getType() != NewTy) - OtherPtr = new BitCastInst(OtherPtr, NewTy, OtherPtr->getName(), MI); - } - - // Process each element of the aggregate. - bool SROADest = MI->getRawDest() == Inst; - - Constant *Zero = Constant::getNullValue(Type::getInt32Ty(MI->getContext())); - const DataLayout &DL = MI->getModule()->getDataLayout(); - - for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { - // If this is a memcpy/memmove, emit a GEP of the other element address. - Value *OtherElt = nullptr; - unsigned OtherEltAlign = MemAlignment; - - if (OtherPtr) { - Value *Idx[2] = { Zero, - ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) }; - OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx, - OtherPtr->getName()+"."+Twine(i), - MI); - uint64_t EltOffset; - PointerType *OtherPtrTy = cast<PointerType>(OtherPtr->getType()); - Type *OtherTy = OtherPtrTy->getElementType(); - if (StructType *ST = dyn_cast<StructType>(OtherTy)) { - EltOffset = DL.getStructLayout(ST)->getElementOffset(i); - } else { - Type *EltTy = cast<SequentialType>(OtherTy)->getElementType(); - EltOffset = DL.getTypeAllocSize(EltTy) * i; - } - - // The alignment of the other pointer is the guaranteed alignment of the - // element, which is affected by both the known alignment of the whole - // mem intrinsic and the alignment of the element. If the alignment of - // the memcpy (f.e.) is 32 but the element is at a 4-byte offset, then the - // known alignment is just 4 bytes. - OtherEltAlign = (unsigned)MinAlign(OtherEltAlign, EltOffset); - } - - Value *EltPtr = NewElts[i]; - Type *EltTy = cast<PointerType>(EltPtr->getType())->getElementType(); - - // If we got down to a scalar, insert a load or store as appropriate. - if (EltTy->isSingleValueType()) { - if (isa<MemTransferInst>(MI)) { - if (SROADest) { - // From Other to Alloca. - Value *Elt = new LoadInst(OtherElt, "tmp", false, OtherEltAlign, MI); - new StoreInst(Elt, EltPtr, MI); - } else { - // From Alloca to Other. - Value *Elt = new LoadInst(EltPtr, "tmp", MI); - new StoreInst(Elt, OtherElt, false, OtherEltAlign, MI); - } - continue; - } - assert(isa<MemSetInst>(MI)); - - // If the stored element is zero (common case), just store a null - // constant. - Constant *StoreVal; - if (ConstantInt *CI = dyn_cast<ConstantInt>(MI->getArgOperand(1))) { - if (CI->isZero()) { - StoreVal = Constant::getNullValue(EltTy); // 0.0, null, 0, <0,0> - } else { - // If EltTy is a vector type, get the element type. - Type *ValTy = EltTy->getScalarType(); - - // Construct an integer with the right value. - unsigned EltSize = DL.getTypeSizeInBits(ValTy); - APInt OneVal(EltSize, CI->getZExtValue()); - APInt TotalVal(OneVal); - // Set each byte. - for (unsigned i = 0; 8*i < EltSize; ++i) { - TotalVal = TotalVal.shl(8); - TotalVal |= OneVal; - } - - // Convert the integer value to the appropriate type. - StoreVal = ConstantInt::get(CI->getContext(), TotalVal); - if (ValTy->isPointerTy()) - StoreVal = ConstantExpr::getIntToPtr(StoreVal, ValTy); - else if (ValTy->isFloatingPointTy()) - StoreVal = ConstantExpr::getBitCast(StoreVal, ValTy); - assert(StoreVal->getType() == ValTy && "Type mismatch!"); - - // If the requested value was a vector constant, create it. - if (EltTy->isVectorTy()) { - unsigned NumElts = cast<VectorType>(EltTy)->getNumElements(); - StoreVal = ConstantVector::getSplat(NumElts, StoreVal); - } - } - new StoreInst(StoreVal, EltPtr, MI); - continue; - } - // Otherwise, if we're storing a byte variable, use a memset call for - // this element. - } - - unsigned EltSize = DL.getTypeAllocSize(EltTy); - if (!EltSize) - continue; - - IRBuilder<> Builder(MI); - - // Finally, insert the meminst for this element. - if (isa<MemSetInst>(MI)) { - Builder.CreateMemSet(EltPtr, MI->getArgOperand(1), EltSize, - MI->isVolatile()); - } else { - assert(isa<MemTransferInst>(MI)); - Value *Dst = SROADest ? EltPtr : OtherElt; // Dest ptr - Value *Src = SROADest ? OtherElt : EltPtr; // Src ptr - - if (isa<MemCpyInst>(MI)) - Builder.CreateMemCpy(Dst, Src, EltSize, OtherEltAlign,MI->isVolatile()); - else - Builder.CreateMemMove(Dst, Src, EltSize,OtherEltAlign,MI->isVolatile()); - } - } - DeadInsts.push_back(MI); -} - -/// RewriteStoreUserOfWholeAlloca - We found a store of an integer that -/// overwrites the entire allocation. Extract out the pieces of the stored -/// integer and store them individually. -void -SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI, - SmallVectorImpl<AllocaInst *> &NewElts) { - // Extract each element out of the integer according to its structure offset - // and store the element value to the individual alloca. - Value *SrcVal = SI->getOperand(0); - Type *AllocaEltTy = AI->getAllocatedType(); - const DataLayout &DL = SI->getModule()->getDataLayout(); - uint64_t AllocaSizeBits = DL.getTypeAllocSizeInBits(AllocaEltTy); - - IRBuilder<> Builder(SI); - - // Handle tail padding by extending the operand - if (DL.getTypeSizeInBits(SrcVal->getType()) != AllocaSizeBits) - SrcVal = Builder.CreateZExt(SrcVal, - IntegerType::get(SI->getContext(), AllocaSizeBits)); - - DEBUG(dbgs() << "PROMOTING STORE TO WHOLE ALLOCA: " << *AI << '\n' << *SI - << '\n'); - - // There are two forms here: AI could be an array or struct. Both cases - // have different ways to compute the element offset. - if (StructType *EltSTy = dyn_cast<StructType>(AllocaEltTy)) { - const StructLayout *Layout = DL.getStructLayout(EltSTy); - - for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { - // Get the number of bits to shift SrcVal to get the value. - Type *FieldTy = EltSTy->getElementType(i); - uint64_t Shift = Layout->getElementOffsetInBits(i); - - if (DL.isBigEndian()) - Shift = AllocaSizeBits - Shift - DL.getTypeAllocSizeInBits(FieldTy); - - Value *EltVal = SrcVal; - if (Shift) { - Value *ShiftVal = ConstantInt::get(EltVal->getType(), Shift); - EltVal = Builder.CreateLShr(EltVal, ShiftVal, "sroa.store.elt"); - } - - // Truncate down to an integer of the right size. - uint64_t FieldSizeBits = DL.getTypeSizeInBits(FieldTy); - - // Ignore zero sized fields like {}, they obviously contain no data. - if (FieldSizeBits == 0) continue; - - if (FieldSizeBits != AllocaSizeBits) - EltVal = Builder.CreateTrunc(EltVal, - IntegerType::get(SI->getContext(), FieldSizeBits)); - Value *DestField = NewElts[i]; - if (EltVal->getType() == FieldTy) { - // Storing to an integer field of this size, just do it. - } else if (FieldTy->isFloatingPointTy() || FieldTy->isVectorTy()) { - // Bitcast to the right element type (for fp/vector values). - EltVal = Builder.CreateBitCast(EltVal, FieldTy); - } else { - // Otherwise, bitcast the dest pointer (for aggregates). - DestField = Builder.CreateBitCast(DestField, - PointerType::getUnqual(EltVal->getType())); - } - new StoreInst(EltVal, DestField, SI); - } - - } else { - ArrayType *ATy = cast<ArrayType>(AllocaEltTy); - Type *ArrayEltTy = ATy->getElementType(); - uint64_t ElementOffset = DL.getTypeAllocSizeInBits(ArrayEltTy); - uint64_t ElementSizeBits = DL.getTypeSizeInBits(ArrayEltTy); - - uint64_t Shift; - - if (DL.isBigEndian()) - Shift = AllocaSizeBits-ElementOffset; - else - Shift = 0; - - for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { - // Ignore zero sized fields like {}, they obviously contain no data. - if (ElementSizeBits == 0) continue; - - Value *EltVal = SrcVal; - if (Shift) { - Value *ShiftVal = ConstantInt::get(EltVal->getType(), Shift); - EltVal = Builder.CreateLShr(EltVal, ShiftVal, "sroa.store.elt"); - } - - // Truncate down to an integer of the right size. - if (ElementSizeBits != AllocaSizeBits) - EltVal = Builder.CreateTrunc(EltVal, - IntegerType::get(SI->getContext(), - ElementSizeBits)); - Value *DestField = NewElts[i]; - if (EltVal->getType() == ArrayEltTy) { - // Storing to an integer field of this size, just do it. - } else if (ArrayEltTy->isFloatingPointTy() || - ArrayEltTy->isVectorTy()) { - // Bitcast to the right element type (for fp/vector values). - EltVal = Builder.CreateBitCast(EltVal, ArrayEltTy); - } else { - // Otherwise, bitcast the dest pointer (for aggregates). - DestField = Builder.CreateBitCast(DestField, - PointerType::getUnqual(EltVal->getType())); - } - new StoreInst(EltVal, DestField, SI); - - if (DL.isBigEndian()) - Shift -= ElementOffset; - else - Shift += ElementOffset; - } - } - - DeadInsts.push_back(SI); -} - -/// RewriteLoadUserOfWholeAlloca - We found a load of the entire allocation to -/// an integer. Load the individual pieces to form the aggregate value. -void -SROA::RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI, - SmallVectorImpl<AllocaInst *> &NewElts) { - // Extract each element out of the NewElts according to its structure offset - // and form the result value. - Type *AllocaEltTy = AI->getAllocatedType(); - const DataLayout &DL = LI->getModule()->getDataLayout(); - uint64_t AllocaSizeBits = DL.getTypeAllocSizeInBits(AllocaEltTy); - - DEBUG(dbgs() << "PROMOTING LOAD OF WHOLE ALLOCA: " << *AI << '\n' << *LI - << '\n'); - - // There are two forms here: AI could be an array or struct. Both cases - // have different ways to compute the element offset. - const StructLayout *Layout = nullptr; - uint64_t ArrayEltBitOffset = 0; - if (StructType *EltSTy = dyn_cast<StructType>(AllocaEltTy)) { - Layout = DL.getStructLayout(EltSTy); - } else { - Type *ArrayEltTy = cast<ArrayType>(AllocaEltTy)->getElementType(); - ArrayEltBitOffset = DL.getTypeAllocSizeInBits(ArrayEltTy); - } - - Value *ResultVal = - Constant::getNullValue(IntegerType::get(LI->getContext(), AllocaSizeBits)); - - for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { - // Load the value from the alloca. If the NewElt is an aggregate, cast - // the pointer to an integer of the same size before doing the load. - Value *SrcField = NewElts[i]; - Type *FieldTy = - cast<PointerType>(SrcField->getType())->getElementType(); - uint64_t FieldSizeBits = DL.getTypeSizeInBits(FieldTy); - - // Ignore zero sized fields like {}, they obviously contain no data. - if (FieldSizeBits == 0) continue; - - IntegerType *FieldIntTy = IntegerType::get(LI->getContext(), - FieldSizeBits); - if (!FieldTy->isIntegerTy() && !FieldTy->isFloatingPointTy() && - !FieldTy->isVectorTy()) - SrcField = new BitCastInst(SrcField, - PointerType::getUnqual(FieldIntTy), - "", LI); - SrcField = new LoadInst(SrcField, "sroa.load.elt", LI); - - // If SrcField is a fp or vector of the right size but that isn't an - // integer type, bitcast to an integer so we can shift it. - if (SrcField->getType() != FieldIntTy) - SrcField = new BitCastInst(SrcField, FieldIntTy, "", LI); - - // Zero extend the field to be the same size as the final alloca so that - // we can shift and insert it. - if (SrcField->getType() != ResultVal->getType()) - SrcField = new ZExtInst(SrcField, ResultVal->getType(), "", LI); - - // Determine the number of bits to shift SrcField. - uint64_t Shift; - if (Layout) // Struct case. - Shift = Layout->getElementOffsetInBits(i); - else // Array case. - Shift = i*ArrayEltBitOffset; - - if (DL.isBigEndian()) - Shift = AllocaSizeBits-Shift-FieldIntTy->getBitWidth(); - - if (Shift) { - Value *ShiftVal = ConstantInt::get(SrcField->getType(), Shift); - SrcField = BinaryOperator::CreateShl(SrcField, ShiftVal, "", LI); - } - - // Don't create an 'or x, 0' on the first iteration. - if (!isa<Constant>(ResultVal) || - !cast<Constant>(ResultVal)->isNullValue()) - ResultVal = BinaryOperator::CreateOr(SrcField, ResultVal, "", LI); - else - ResultVal = SrcField; - } - - // Handle tail padding by truncating the result - if (DL.getTypeSizeInBits(LI->getType()) != AllocaSizeBits) - ResultVal = new TruncInst(ResultVal, LI->getType(), "", LI); - - LI->replaceAllUsesWith(ResultVal); - DeadInsts.push_back(LI); -} - -/// HasPadding - Return true if the specified type has any structure or -/// alignment padding in between the elements that would be split apart -/// by SROA; return false otherwise. -static bool HasPadding(Type *Ty, const DataLayout &DL) { - if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { - Ty = ATy->getElementType(); - return DL.getTypeSizeInBits(Ty) != DL.getTypeAllocSizeInBits(Ty); - } - - // SROA currently handles only Arrays and Structs. - StructType *STy = cast<StructType>(Ty); - const StructLayout *SL = DL.getStructLayout(STy); - unsigned PrevFieldBitOffset = 0; - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - unsigned FieldBitOffset = SL->getElementOffsetInBits(i); - - // Check to see if there is any padding between this element and the - // previous one. - if (i) { - unsigned PrevFieldEnd = - PrevFieldBitOffset+DL.getTypeSizeInBits(STy->getElementType(i-1)); - if (PrevFieldEnd < FieldBitOffset) - return true; - } - PrevFieldBitOffset = FieldBitOffset; - } - // Check for tail padding. - if (unsigned EltCount = STy->getNumElements()) { - unsigned PrevFieldEnd = PrevFieldBitOffset + - DL.getTypeSizeInBits(STy->getElementType(EltCount-1)); - if (PrevFieldEnd < SL->getSizeInBits()) - return true; - } - return false; -} - -/// isSafeStructAllocaToScalarRepl - Check to see if the specified allocation of -/// an aggregate can be broken down into elements. Return 0 if not, 3 if safe, -/// or 1 if safe after canonicalization has been performed. -bool SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) { - // Loop over the use list of the alloca. We can only transform it if all of - // the users are safe to transform. - AllocaInfo Info(AI); - - isSafeForScalarRepl(AI, 0, Info); - if (Info.isUnsafe) { - DEBUG(dbgs() << "Cannot transform: " << *AI << '\n'); - return false; - } - - const DataLayout &DL = AI->getModule()->getDataLayout(); - - // Okay, we know all the users are promotable. If the aggregate is a memcpy - // source and destination, we have to be careful. In particular, the memcpy - // could be moving around elements that live in structure padding of the LLVM - // types, but may actually be used. In these cases, we refuse to promote the - // struct. - if (Info.isMemCpySrc && Info.isMemCpyDst && - HasPadding(AI->getAllocatedType(), DL)) - return false; - - // If the alloca never has an access to just *part* of it, but is accessed - // via loads and stores, then we should use ConvertToScalarInfo to promote - // the alloca instead of promoting each piece at a time and inserting fission - // and fusion code. - if (!Info.hasSubelementAccess && Info.hasALoadOrStore) { - // If the struct/array just has one element, use basic SRoA. - if (StructType *ST = dyn_cast<StructType>(AI->getAllocatedType())) { - if (ST->getNumElements() > 1) return false; - } else { - if (cast<ArrayType>(AI->getAllocatedType())->getNumElements() > 1) - return false; - } - } - - return true; -} diff --git a/gnu/llvm/lib/Transforms/Utils/Makefile b/gnu/llvm/lib/Transforms/Utils/Makefile deleted file mode 100644 index d1e9336d67f..00000000000 --- a/gnu/llvm/lib/Transforms/Utils/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Transforms/Utils/Makefile -----------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMTransformUtils -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - diff --git a/gnu/llvm/lib/Transforms/Vectorize/Makefile b/gnu/llvm/lib/Transforms/Vectorize/Makefile deleted file mode 100644 index 86c36585f23..00000000000 --- a/gnu/llvm/lib/Transforms/Vectorize/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Transforms/Vectorize/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMVectorize -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common - |