<commit_before>//===----- llvm/unittest/ADT/SCCIteratorTest.cpp - SCCIterator tests ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <limits.h>
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SCCIterator.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace llvm {

/// Graph<N> - A graph with N nodes.  Note that N can be at most 8.
template <unsigned N>
class Graph {
private:
  // Disable copying.
  Graph(const Graph&);
  Graph& operator=(const Graph&);

  static void ValidateIndex(unsigned Idx) {
    assert(Idx < N && "Invalid node index!");
  }
public:

  /// NodeSubset - A subset of the graph's nodes.
  class NodeSubset {
    typedef unsigned char BitVector; // Where the limitation N <= 8 comes from.
    BitVector Elements;
    NodeSubset(BitVector e) : Elements(e) {}
  public:
    /// NodeSubset - Default constructor, creates an empty subset.
    NodeSubset() : Elements(0) {
      assert(N <= sizeof(BitVector)*CHAR_BIT && "Graph too big!");
    }
    /// NodeSubset - Copy constructor.
    NodeSubset(const NodeSubset &other) : Elements(other.Elements) {}

    /// Comparison operators.
    bool operator==(const NodeSubset &other) const {
      return other.Elements == this->Elements;
    }
    bool operator!=(const NodeSubset &other) const {
      return !(*this == other);
    }

    /// AddNode - Add the node with the given index to the subset.
    void AddNode(unsigned Idx) {
      ValidateIndex(Idx);
      Elements |= 1U << Idx;
    }

    /// DeleteNode - Remove the node with the given index from the subset.
    void DeleteNode(unsigned Idx) {
      ValidateIndex(Idx);
      Elements &= ~(1U << Idx);
    }

    /// count - Return true if the node with the given index is in the subset.
    bool count(unsigned Idx) {
      ValidateIndex(Idx);
      return (Elements & (1U << Idx)) != 0;
    }

    /// isEmpty - Return true if this is the empty set.
    bool isEmpty() const {
      return Elements == 0;
    }

    /// isSubsetOf - Return true if this set is a subset of the given one.
    bool isSubsetOf(const NodeSubset &other) const {
      return (this->Elements | other.Elements) == other.Elements;
    }

    /// Complement - Return the complement of this subset.
    NodeSubset Complement() const {
      return ~(unsigned)this->Elements & ((1U << N) - 1);
    }

    /// Join - Return the union of this subset and the given one.
    NodeSubset Join(const NodeSubset &other) const {
      return this->Elements | other.Elements;
    }

    /// Meet - Return the intersection of this subset and the given one.
    NodeSubset Meet(const NodeSubset &other) const {
      return this->Elements & other.Elements;
    }
  };

  /// NodeType - Node index and set of children of the node.
  typedef std::pair<unsigned, NodeSubset> NodeType;

private:
  /// Nodes - The list of nodes for this graph.
  NodeType Nodes[N];
public:

  /// Graph - Default constructor.  Creates an empty graph.
  Graph() {
    // Let each node know which node it is.  This allows us to find the start of
    // the Nodes array given a pointer to any element of it.
    for (unsigned i = 0; i != N; ++i)
      Nodes[i].first = i;
  }

  /// AddEdge - Add an edge from the node with index FromIdx to the node with
  /// index ToIdx.
  void AddEdge(unsigned FromIdx, unsigned ToIdx) {
    ValidateIndex(FromIdx);
    Nodes[FromIdx].second.AddNode(ToIdx);
  }

  /// DeleteEdge - Remove the edge (if any) from the node with index FromIdx to
  /// the node with index ToIdx.
  void DeleteEdge(unsigned FromIdx, unsigned ToIdx) {
    ValidateIndex(FromIdx);
    Nodes[FromIdx].second.DeleteNode(ToIdx);
  }

  /// AccessNode - Get a pointer to the node with the given index.
  NodeType *AccessNode(unsigned Idx) const {
    ValidateIndex(Idx);
    // The constant cast is needed when working with GraphTraits, which insists
    // on taking a constant Graph.
    return const_cast<NodeType *>(&Nodes[Idx]);
  }

  /// NodesReachableFrom - Return the set of all nodes reachable from the given
  /// node.
  NodeSubset NodesReachableFrom(unsigned Idx) const {
    // This algorithm doesn't scale, but that doesn't matter given the small
    // size of our graphs.
    NodeSubset Reachable;

    // The initial node is reachable.
    Reachable.AddNode(Idx);
    do {
      NodeSubset Previous(Reachable);

      // Add in all nodes which are children of a reachable node.
      for (unsigned i = 0; i != N; ++i)
        if (Previous.count(i))
          Reachable = Reachable.Join(Nodes[i].second);

      // If nothing changed then we have found all reachable nodes.
      if (Reachable == Previous)
        return Reachable;

      // Rinse and repeat.
    } while (1);
  }

  /// ChildIterator - Visit all children of a node.
  class ChildIterator {
    friend class Graph;

    /// FirstNode - Pointer to first node in the graph's Nodes array.
    NodeType *FirstNode;
    /// Children - Set of nodes which are children of this one and that haven't
    /// yet been visited.
    NodeSubset Children;

    ChildIterator(); // Disable default constructor.
  protected:
    ChildIterator(NodeType *F, NodeSubset C) : FirstNode(F), Children(C) {}

  public:
    /// ChildIterator - Copy constructor.
    ChildIterator(const ChildIterator& other) : FirstNode(other.FirstNode),
      Children(other.Children) {}

    /// Comparison operators.
    bool operator==(const ChildIterator &other) const {
      return other.FirstNode == this->FirstNode &&
        other.Children == this->Children;
    }
    bool operator!=(const ChildIterator &other) const {
      return !(*this == other);
    }

    /// Prefix increment operator.
    ChildIterator& operator++() {
      // Find the next unvisited child node.
      for (unsigned i = 0; i != N; ++i)
        if (Children.count(i)) {
          // Remove that child - it has been visited.  This is the increment!
          Children.DeleteNode(i);
          return *this;
        }
      assert(false && "Incrementing end iterator!");
      return *this; // Avoid compiler warnings.
    }

    /// Postfix increment operator.
    ChildIterator operator++(int) {
      ChildIterator Result(*this);
      ++(*this);
      return Result;
    }

    /// Dereference operator.
    NodeType *operator*() {
      // Find the next unvisited child node.
      for (unsigned i = 0; i != N; ++i)
        if (Children.count(i))
          // Return a pointer to it.
          return FirstNode + i;
      assert(false && "Dereferencing end iterator!");
      return 0; // Avoid compiler warning.
    }
  };

  /// child_begin - Return an iterator pointing to the first child of the given
  /// node.
  static ChildIterator child_begin(NodeType *Parent) {
    return ChildIterator(Parent - Parent->first, Parent->second);
  }

  /// child_end - Return the end iterator for children of the given node.
  static ChildIterator child_end(NodeType *Parent) {
    return ChildIterator(Parent - Parent->first, NodeSubset());
  }
};

template <unsigned N>
struct GraphTraits<Graph<N> > {
  typedef typename Graph<N>::NodeType NodeType;
  typedef typename Graph<N>::ChildIterator ChildIteratorType;

 static inline NodeType *getEntryNode(const Graph<N> &G) { return G.AccessNode(0); }
 static inline ChildIteratorType child_begin(NodeType *Node) {
   return Graph<N>::child_begin(Node);
 }
 static inline ChildIteratorType child_end(NodeType *Node) {
   return Graph<N>::child_end(Node);
 }
};

TEST(SCCIteratorTest, AllSmallGraphs) {
  // Test SCC computation against every graph with NUM_NODES nodes or less.
  // Since SCC considers every node to have an implicit self-edge, we only
  // create graphs for which every node has a self-edge.
#define NUM_NODES 4
#define NUM_GRAPHS (NUM_NODES * (NUM_NODES - 1))

  /// GraphDescriptor - Enumerate all graphs using NUM_GRAPHS bits.
  unsigned GraphDescriptor = 0;
  assert(NUM_GRAPHS <= sizeof(unsigned) * CHAR_BIT && "Too many graphs!");

  do {
    typedef Graph<NUM_NODES> GT;

    GT G;

    // Add edges as specified by the descriptor.
    unsigned DescriptorCopy = GraphDescriptor;
    for (unsigned i = 0; i != NUM_NODES; ++i)
      for (unsigned j = 0; j != NUM_NODES; ++j) {
        // Always add a self-edge.
        if (i == j) {
          G.AddEdge(i, j);
          continue;
        }
        if (DescriptorCopy & 1)
          G.AddEdge(i, j);
        DescriptorCopy >>= 1;
      }

    // Test the SCC logic on this graph.

    /// NodesInSomeSCC - Those nodes which are in some SCC.
    GT::NodeSubset NodesInSomeSCC;

    for (scc_iterator<GT> I = scc_begin(G), E = scc_end(G); I != E; ++I) {
      std::vector<GT::NodeType*> &SCC = *I;

      // Get the nodes in this SCC as a NodeSubset rather than a vector.
      GT::NodeSubset NodesInThisSCC;
      for (unsigned i = 0, e = SCC.size(); i != e; ++i)
        NodesInThisSCC.AddNode(SCC[i]->first);

      // There should be at least one node in every SCC.
      EXPECT_FALSE(NodesInThisSCC.isEmpty());

      // Check that every node in the SCC is reachable from every other node in
      // the SCC.
      for (unsigned i = 0; i != NUM_NODES; ++i)
        if (NodesInThisSCC.count(i))
          EXPECT_TRUE(NodesInThisSCC.isSubsetOf(G.NodesReachableFrom(i)));

      // OK, now that we now that every node in the SCC is reachable from every
      // other, this means that the set of nodes reachable from any node in the
      // SCC is the same as the set of nodes reachable from every node in the
      // SCC.  Check that for every node N not in the SCC but reachable from the
      // SCC, no element of the SCC is reachable from N.
      for (unsigned i = 0; i != NUM_NODES; ++i)
        if (NodesInThisSCC.count(i)) {
          GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i);
          GT::NodeSubset ReachableButNotInSCC =
            NodesReachableFromSCC.Meet(NodesInThisSCC.Complement());

          for (unsigned j = 0; j != NUM_NODES; ++j)
            if (ReachableButNotInSCC.count(j))
              EXPECT_TRUE(G.NodesReachableFrom(j).Meet(NodesInThisSCC).isEmpty());

          // The result must be the same for all other nodes in this SCC, so
          // there is no point in checking them.
          break;
        }

      // This is indeed a SCC: a maximal set of nodes for which each node is
      // reachable from every other.

      // Check that we didn't already see this SCC.
      EXPECT_TRUE(NodesInSomeSCC.Meet(NodesInThisSCC).isEmpty());

      NodesInSomeSCC = NodesInSomeSCC.Join(NodesInThisSCC);

      // Check a property that is specific to the LLVM SCC iterator and
      // guaranteed by it: if a node in SCC S1 has an edge to a node in
      // SCC S2, then S1 is visited *after* S2.  This means that the set
      // of nodes reachable from this SCC must be contained either in the
      // union of this SCC and all previously visited SCC's.

      for (unsigned i = 0; i != NUM_NODES; ++i)
        if (NodesInThisSCC.count(i)) {
          GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i);
          EXPECT_TRUE(NodesReachableFromSCC.isSubsetOf(NodesInSomeSCC));
          // The result must be the same for all other nodes in this SCC, so
          // there is no point in checking them.
          break;
        }
    }

    // Finally, check that the nodes in some SCC are exactly those that are
    // reachable from the initial node.
    EXPECT_EQ(NodesInSomeSCC, G.NodesReachableFrom(0));

    ++GraphDescriptor;
  } while (GraphDescriptor && GraphDescriptor < (1U << NUM_GRAPHS));
}

}
<commit_msg>Avoid undefined behaviour if somehow NUM_GRAPHS equals 2^32 (or whatever the size of unsigned is), though this can't actually occur for any integer value of NUM_NODES.<commit_after>//===----- llvm/unittest/ADT/SCCIteratorTest.cpp - SCCIterator tests ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <limits.h>
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SCCIterator.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace llvm {

/// Graph<N> - A graph with N nodes.  Note that N can be at most 8.
template <unsigned N>
class Graph {
private:
  // Disable copying.
  Graph(const Graph&);
  Graph& operator=(const Graph&);

  static void ValidateIndex(unsigned Idx) {
    assert(Idx < N && "Invalid node index!");
  }
public:

  /// NodeSubset - A subset of the graph's nodes.
  class NodeSubset {
    typedef unsigned char BitVector; // Where the limitation N <= 8 comes from.
    BitVector Elements;
    NodeSubset(BitVector e) : Elements(e) {}
  public:
    /// NodeSubset - Default constructor, creates an empty subset.
    NodeSubset() : Elements(0) {
      assert(N <= sizeof(BitVector)*CHAR_BIT && "Graph too big!");
    }
    /// NodeSubset - Copy constructor.
    NodeSubset(const NodeSubset &other) : Elements(other.Elements) {}

    /// Comparison operators.
    bool operator==(const NodeSubset &other) const {
      return other.Elements == this->Elements;
    }
    bool operator!=(const NodeSubset &other) const {
      return !(*this == other);
    }

    /// AddNode - Add the node with the given index to the subset.
    void AddNode(unsigned Idx) {
      ValidateIndex(Idx);
      Elements |= 1U << Idx;
    }

    /// DeleteNode - Remove the node with the given index from the subset.
    void DeleteNode(unsigned Idx) {
      ValidateIndex(Idx);
      Elements &= ~(1U << Idx);
    }

    /// count - Return true if the node with the given index is in the subset.
    bool count(unsigned Idx) {
      ValidateIndex(Idx);
      return (Elements & (1U << Idx)) != 0;
    }

    /// isEmpty - Return true if this is the empty set.
    bool isEmpty() const {
      return Elements == 0;
    }

    /// isSubsetOf - Return true if this set is a subset of the given one.
    bool isSubsetOf(const NodeSubset &other) const {
      return (this->Elements | other.Elements) == other.Elements;
    }

    /// Complement - Return the complement of this subset.
    NodeSubset Complement() const {
      return ~(unsigned)this->Elements & ((1U << N) - 1);
    }

    /// Join - Return the union of this subset and the given one.
    NodeSubset Join(const NodeSubset &other) const {
      return this->Elements | other.Elements;
    }

    /// Meet - Return the intersection of this subset and the given one.
    NodeSubset Meet(const NodeSubset &other) const {
      return this->Elements & other.Elements;
    }
  };

  /// NodeType - Node index and set of children of the node.
  typedef std::pair<unsigned, NodeSubset> NodeType;

private:
  /// Nodes - The list of nodes for this graph.
  NodeType Nodes[N];
public:

  /// Graph - Default constructor.  Creates an empty graph.
  Graph() {
    // Let each node know which node it is.  This allows us to find the start of
    // the Nodes array given a pointer to any element of it.
    for (unsigned i = 0; i != N; ++i)
      Nodes[i].first = i;
  }

  /// AddEdge - Add an edge from the node with index FromIdx to the node with
  /// index ToIdx.
  void AddEdge(unsigned FromIdx, unsigned ToIdx) {
    ValidateIndex(FromIdx);
    Nodes[FromIdx].second.AddNode(ToIdx);
  }

  /// DeleteEdge - Remove the edge (if any) from the node with index FromIdx to
  /// the node with index ToIdx.
  void DeleteEdge(unsigned FromIdx, unsigned ToIdx) {
    ValidateIndex(FromIdx);
    Nodes[FromIdx].second.DeleteNode(ToIdx);
  }

  /// AccessNode - Get a pointer to the node with the given index.
  NodeType *AccessNode(unsigned Idx) const {
    ValidateIndex(Idx);
    // The constant cast is needed when working with GraphTraits, which insists
    // on taking a constant Graph.
    return const_cast<NodeType *>(&Nodes[Idx]);
  }

  /// NodesReachableFrom - Return the set of all nodes reachable from the given
  /// node.
  NodeSubset NodesReachableFrom(unsigned Idx) const {
    // This algorithm doesn't scale, but that doesn't matter given the small
    // size of our graphs.
    NodeSubset Reachable;

    // The initial node is reachable.
    Reachable.AddNode(Idx);
    do {
      NodeSubset Previous(Reachable);

      // Add in all nodes which are children of a reachable node.
      for (unsigned i = 0; i != N; ++i)
        if (Previous.count(i))
          Reachable = Reachable.Join(Nodes[i].second);

      // If nothing changed then we have found all reachable nodes.
      if (Reachable == Previous)
        return Reachable;

      // Rinse and repeat.
    } while (1);
  }

  /// ChildIterator - Visit all children of a node.
  class ChildIterator {
    friend class Graph;

    /// FirstNode - Pointer to first node in the graph's Nodes array.
    NodeType *FirstNode;
    /// Children - Set of nodes which are children of this one and that haven't
    /// yet been visited.
    NodeSubset Children;

    ChildIterator(); // Disable default constructor.
  protected:
    ChildIterator(NodeType *F, NodeSubset C) : FirstNode(F), Children(C) {}

  public:
    /// ChildIterator - Copy constructor.
    ChildIterator(const ChildIterator& other) : FirstNode(other.FirstNode),
      Children(other.Children) {}

    /// Comparison operators.
    bool operator==(const ChildIterator &other) const {
      return other.FirstNode == this->FirstNode &&
        other.Children == this->Children;
    }
    bool operator!=(const ChildIterator &other) const {
      return !(*this == other);
    }

    /// Prefix increment operator.
    ChildIterator& operator++() {
      // Find the next unvisited child node.
      for (unsigned i = 0; i != N; ++i)
        if (Children.count(i)) {
          // Remove that child - it has been visited.  This is the increment!
          Children.DeleteNode(i);
          return *this;
        }
      assert(false && "Incrementing end iterator!");
      return *this; // Avoid compiler warnings.
    }

    /// Postfix increment operator.
    ChildIterator operator++(int) {
      ChildIterator Result(*this);
      ++(*this);
      return Result;
    }

    /// Dereference operator.
    NodeType *operator*() {
      // Find the next unvisited child node.
      for (unsigned i = 0; i != N; ++i)
        if (Children.count(i))
          // Return a pointer to it.
          return FirstNode + i;
      assert(false && "Dereferencing end iterator!");
      return 0; // Avoid compiler warning.
    }
  };

  /// child_begin - Return an iterator pointing to the first child of the given
  /// node.
  static ChildIterator child_begin(NodeType *Parent) {
    return ChildIterator(Parent - Parent->first, Parent->second);
  }

  /// child_end - Return the end iterator for children of the given node.
  static ChildIterator child_end(NodeType *Parent) {
    return ChildIterator(Parent - Parent->first, NodeSubset());
  }
};

template <unsigned N>
struct GraphTraits<Graph<N> > {
  typedef typename Graph<N>::NodeType NodeType;
  typedef typename Graph<N>::ChildIterator ChildIteratorType;

 static inline NodeType *getEntryNode(const Graph<N> &G) { return G.AccessNode(0); }
 static inline ChildIteratorType child_begin(NodeType *Node) {
   return Graph<N>::child_begin(Node);
 }
 static inline ChildIteratorType child_end(NodeType *Node) {
   return Graph<N>::child_end(Node);
 }
};

TEST(SCCIteratorTest, AllSmallGraphs) {
  // Test SCC computation against every graph with NUM_NODES nodes or less.
  // Since SCC considers every node to have an implicit self-edge, we only
  // create graphs for which every node has a self-edge.
#define NUM_NODES 4
#define NUM_GRAPHS (NUM_NODES * (NUM_NODES - 1))
  typedef Graph<NUM_NODES> GT;

  /// Enumerate all graphs using NUM_GRAPHS bits.
  assert(NUM_GRAPHS < sizeof(unsigned) * CHAR_BIT && "Too many graphs!");
  for (unsigned GraphDescriptor = 0; GraphDescriptor < (1U << NUM_GRAPHS);
       ++GraphDescriptor) {
    GT G;

    // Add edges as specified by the descriptor.
    unsigned DescriptorCopy = GraphDescriptor;
    for (unsigned i = 0; i != NUM_NODES; ++i)
      for (unsigned j = 0; j != NUM_NODES; ++j) {
        // Always add a self-edge.
        if (i == j) {
          G.AddEdge(i, j);
          continue;
        }
        if (DescriptorCopy & 1)
          G.AddEdge(i, j);
        DescriptorCopy >>= 1;
      }

    // Test the SCC logic on this graph.

    /// NodesInSomeSCC - Those nodes which are in some SCC.
    GT::NodeSubset NodesInSomeSCC;

    for (scc_iterator<GT> I = scc_begin(G), E = scc_end(G); I != E; ++I) {
      std::vector<GT::NodeType*> &SCC = *I;

      // Get the nodes in this SCC as a NodeSubset rather than a vector.
      GT::NodeSubset NodesInThisSCC;
      for (unsigned i = 0, e = SCC.size(); i != e; ++i)
        NodesInThisSCC.AddNode(SCC[i]->first);

      // There should be at least one node in every SCC.
      EXPECT_FALSE(NodesInThisSCC.isEmpty());

      // Check that every node in the SCC is reachable from every other node in
      // the SCC.
      for (unsigned i = 0; i != NUM_NODES; ++i)
        if (NodesInThisSCC.count(i))
          EXPECT_TRUE(NodesInThisSCC.isSubsetOf(G.NodesReachableFrom(i)));

      // OK, now that we now that every node in the SCC is reachable from every
      // other, this means that the set of nodes reachable from any node in the
      // SCC is the same as the set of nodes reachable from every node in the
      // SCC.  Check that for every node N not in the SCC but reachable from the
      // SCC, no element of the SCC is reachable from N.
      for (unsigned i = 0; i != NUM_NODES; ++i)
        if (NodesInThisSCC.count(i)) {
          GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i);
          GT::NodeSubset ReachableButNotInSCC =
            NodesReachableFromSCC.Meet(NodesInThisSCC.Complement());

          for (unsigned j = 0; j != NUM_NODES; ++j)
            if (ReachableButNotInSCC.count(j))
              EXPECT_TRUE(G.NodesReachableFrom(j).Meet(NodesInThisSCC).isEmpty());

          // The result must be the same for all other nodes in this SCC, so
          // there is no point in checking them.
          break;
        }

      // This is indeed a SCC: a maximal set of nodes for which each node is
      // reachable from every other.

      // Check that we didn't already see this SCC.
      EXPECT_TRUE(NodesInSomeSCC.Meet(NodesInThisSCC).isEmpty());

      NodesInSomeSCC = NodesInSomeSCC.Join(NodesInThisSCC);

      // Check a property that is specific to the LLVM SCC iterator and
      // guaranteed by it: if a node in SCC S1 has an edge to a node in
      // SCC S2, then S1 is visited *after* S2.  This means that the set
      // of nodes reachable from this SCC must be contained either in the
      // union of this SCC and all previously visited SCC's.

      for (unsigned i = 0; i != NUM_NODES; ++i)
        if (NodesInThisSCC.count(i)) {
          GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i);
          EXPECT_TRUE(NodesReachableFromSCC.isSubsetOf(NodesInSomeSCC));
          // The result must be the same for all other nodes in this SCC, so
          // there is no point in checking them.
          break;
        }
    }

    // Finally, check that the nodes in some SCC are exactly those that are
    // reachable from the initial node.
    EXPECT_EQ(NodesInSomeSCC, G.NodesReachableFrom(0));
  }
}

}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.H"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/IR/LegacyPassManager.h"

using namespace llvm;

namespace llvm {
  void initializeTestPassPass(PassRegistry &);
}

namespace {

void initLLVM() {
  InitializeAllTargets();
  InitializeAllTargetMCs();
  InitializeAllAsmPrinters();
  InitializeAllAsmParsers();

  PassRegistry *Registry = PassRegistry::getPassRegistry();
  initializeCore(*Registry);
  initializeCodeGen(*Registry);
}

/// Create a TargetMachine. As we lack a dedicated always available target for
/// unittests, we go for "x86_64" which should be available in most builds.
std::unique_ptr<TargetMachine> createTargetMachine() {
  Triple TargetTriple("x86_64--");
  std::string Error;
  const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
  if (!T)
    return nullptr;

  TargetOptions Options;
  return std::unique_ptr<TargetMachine>(
      T->createTargetMachine("x86_64", "", "", Options, Reloc::Default,
                             CodeModel::Default, CodeGenOpt::Aggressive));
}

std::unique_ptr<Module> parseMIR(legacy::PassManagerBase &PM,
    std::unique_ptr<MIRParser> &MIR, const TargetMachine &TM,
    StringRef MIRCode, const char *FuncName) {
  LLVMContext &Context = getGlobalContext();

  SMDiagnostic Diagnostic;
  std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
  MIR = std::move(createMIRParser(std::move(MBuffer), Context));
  if (!MIR)
    return nullptr;

  std::unique_ptr<Module> M = MIR->parseLLVMModule();
  if (!M)
    return nullptr;

  M->setDataLayout(TM.createDataLayout());

  Function *F = M->getFunction(FuncName);
  if (!F)
    return nullptr;

  MachineModuleInfo *MMI = new MachineModuleInfo(
      *TM.getMCAsmInfo(), *TM.getMCRegisterInfo(), nullptr);
  PM.add(MMI);

  MachineFunctionAnalysis *MFA = new MachineFunctionAnalysis(TM, MIR.get());
  PM.add(MFA);

  return M;
}

typedef std::function<void(MachineFunction&,LiveIntervals&)> LiveIntervalTest;

struct TestPass : public MachineFunctionPass {
  static char ID;
  TestPass() : MachineFunctionPass(ID) {
    // We should never call this but always use PM.add(new TestPass(...))
    abort();
  }
  TestPass(LiveIntervalTest T) : MachineFunctionPass(ID), T(T) {
    initializeTestPassPass(*PassRegistry::getPassRegistry());
  }

  bool runOnMachineFunction(MachineFunction &MF) override {
    LiveIntervals &LIS = getAnalysis<LiveIntervals>();
    T(MF, LIS);
    EXPECT_TRUE(MF.verify(this));
    return true;
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesAll();
    AU.addRequired<LiveIntervals>();
    AU.addPreserved<LiveIntervals>();
    MachineFunctionPass::getAnalysisUsage(AU);
  }
private:
  LiveIntervalTest T;
};

/**
 * Move instruction number \p From in front of instruction number \p To and
 * update affected liveness intervals with LiveIntervalAnalysis::handleMove().
 */
void Move(MachineFunction &MF, LiveIntervals &LIS, unsigned From, unsigned To) {
  MachineBasicBlock &MBB = MF.front();

  unsigned I = 0;
  MachineInstr *FromInstr = nullptr;
  MachineInstr *ToInstr = nullptr;
  for (MachineInstr &MI : MBB) {
    if (I == From)
      FromInstr = &MI;
    if (I == To)
      ToInstr = &MI;
    ++I;
  }
  assert(FromInstr != nullptr && ToInstr != nullptr);

  MBB.splice(ToInstr->getIterator(), &MBB, FromInstr->getIterator());
  LIS.handleMove(FromInstr, true);
}

void DoLiveIntervalTest(StringRef MIRFunc, LiveIntervalTest T) {
  std::unique_ptr<TargetMachine> TM = createTargetMachine();
  // This test is designed for the X86 backend; stop if it is not available.
  if (!TM)
    return;

  legacy::PassManager PM;

  SmallString<160> S;
  StringRef MIRString = (Twine(
"---\n"
"...\n"
"name: func\n"
"registers:\n"
"  - { id: 0, class: gr64 }\n"
"body: |\n"
"  bb.0:\n"
  ) + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
  std::unique_ptr<MIRParser> MIR;
  std::unique_ptr<Module> M = parseMIR(PM, MIR, *TM, MIRString, "func");

  PM.add(new TestPass(T));

  PM.run(*M);
}

} // End of anonymous namespace.

char TestPass::ID = 0;
INITIALIZE_PASS(TestPass, "testpass", "testpass", false, false)

TEST(LiveIntervalTest, MoveUpDef) {
  // Value defined.
  DoLiveIntervalTest(
"    NOOP\n"
"    NOOP\n"
"    early-clobber %0 = IMPLICIT_DEF\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

TEST(LiveIntervalTest, MoveUpRedef) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

TEST(LiveIntervalTest, MoveUpEarlyDef) {
  DoLiveIntervalTest(
"    NOOP\n"
"    NOOP\n"
"    early-clobber %0 = IMPLICIT_DEF\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

TEST(LiveIntervalTest, MoveUpEarlyRedef) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

TEST(LiveIntervalTest, MoveUpKill) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    NOOP implicit %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

TEST(LiveIntervalTest, MoveUpKillFollowing) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    NOOP implicit %0\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

// TODO: Construct a situation where we have intervals following a hole
// while still having connected components.

TEST(LiveIntervalTest, MoveDownDef) {
  // Value defined.
  DoLiveIntervalTest(
"    NOOP\n"
"    early-clobber %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

TEST(LiveIntervalTest, MoveDownRedef) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
"    NOOP\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

TEST(LiveIntervalTest, MoveDownEarlyDef) {
  DoLiveIntervalTest(
"    NOOP\n"
"    early-clobber %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

TEST(LiveIntervalTest, MoveDownEarlyRedef) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
"    NOOP\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

TEST(LiveIntervalTest, MoveDownKill) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP implicit %0\n"
"    NOOP\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

TEST(LiveIntervalTest, MoveDownKillFollowing) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    NOOP implicit %0\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  initLLVM();
  return RUN_ALL_TESTS();
}
<commit_msg>Fix typo in LiveIntervalTest<commit_after>#include "gtest/gtest.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/IR/LegacyPassManager.h"

using namespace llvm;

namespace llvm {
  void initializeTestPassPass(PassRegistry &);
}

namespace {

void initLLVM() {
  InitializeAllTargets();
  InitializeAllTargetMCs();
  InitializeAllAsmPrinters();
  InitializeAllAsmParsers();

  PassRegistry *Registry = PassRegistry::getPassRegistry();
  initializeCore(*Registry);
  initializeCodeGen(*Registry);
}

/// Create a TargetMachine. As we lack a dedicated always available target for
/// unittests, we go for "x86_64" which should be available in most builds.
std::unique_ptr<TargetMachine> createTargetMachine() {
  Triple TargetTriple("x86_64--");
  std::string Error;
  const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
  if (!T)
    return nullptr;

  TargetOptions Options;
  return std::unique_ptr<TargetMachine>(
      T->createTargetMachine("x86_64", "", "", Options, Reloc::Default,
                             CodeModel::Default, CodeGenOpt::Aggressive));
}

std::unique_ptr<Module> parseMIR(legacy::PassManagerBase &PM,
    std::unique_ptr<MIRParser> &MIR, const TargetMachine &TM,
    StringRef MIRCode, const char *FuncName) {
  LLVMContext &Context = getGlobalContext();

  SMDiagnostic Diagnostic;
  std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
  MIR = std::move(createMIRParser(std::move(MBuffer), Context));
  if (!MIR)
    return nullptr;

  std::unique_ptr<Module> M = MIR->parseLLVMModule();
  if (!M)
    return nullptr;

  M->setDataLayout(TM.createDataLayout());

  Function *F = M->getFunction(FuncName);
  if (!F)
    return nullptr;

  MachineModuleInfo *MMI = new MachineModuleInfo(
      *TM.getMCAsmInfo(), *TM.getMCRegisterInfo(), nullptr);
  PM.add(MMI);

  MachineFunctionAnalysis *MFA = new MachineFunctionAnalysis(TM, MIR.get());
  PM.add(MFA);

  return M;
}

typedef std::function<void(MachineFunction&,LiveIntervals&)> LiveIntervalTest;

struct TestPass : public MachineFunctionPass {
  static char ID;
  TestPass() : MachineFunctionPass(ID) {
    // We should never call this but always use PM.add(new TestPass(...))
    abort();
  }
  TestPass(LiveIntervalTest T) : MachineFunctionPass(ID), T(T) {
    initializeTestPassPass(*PassRegistry::getPassRegistry());
  }

  bool runOnMachineFunction(MachineFunction &MF) override {
    LiveIntervals &LIS = getAnalysis<LiveIntervals>();
    T(MF, LIS);
    EXPECT_TRUE(MF.verify(this));
    return true;
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesAll();
    AU.addRequired<LiveIntervals>();
    AU.addPreserved<LiveIntervals>();
    MachineFunctionPass::getAnalysisUsage(AU);
  }
private:
  LiveIntervalTest T;
};

/**
 * Move instruction number \p From in front of instruction number \p To and
 * update affected liveness intervals with LiveIntervalAnalysis::handleMove().
 */
void Move(MachineFunction &MF, LiveIntervals &LIS, unsigned From, unsigned To) {
  MachineBasicBlock &MBB = MF.front();

  unsigned I = 0;
  MachineInstr *FromInstr = nullptr;
  MachineInstr *ToInstr = nullptr;
  for (MachineInstr &MI : MBB) {
    if (I == From)
      FromInstr = &MI;
    if (I == To)
      ToInstr = &MI;
    ++I;
  }
  assert(FromInstr != nullptr && ToInstr != nullptr);

  MBB.splice(ToInstr->getIterator(), &MBB, FromInstr->getIterator());
  LIS.handleMove(FromInstr, true);
}

void DoLiveIntervalTest(StringRef MIRFunc, LiveIntervalTest T) {
  std::unique_ptr<TargetMachine> TM = createTargetMachine();
  // This test is designed for the X86 backend; stop if it is not available.
  if (!TM)
    return;

  legacy::PassManager PM;

  SmallString<160> S;
  StringRef MIRString = (Twine(
"---\n"
"...\n"
"name: func\n"
"registers:\n"
"  - { id: 0, class: gr64 }\n"
"body: |\n"
"  bb.0:\n"
  ) + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
  std::unique_ptr<MIRParser> MIR;
  std::unique_ptr<Module> M = parseMIR(PM, MIR, *TM, MIRString, "func");

  PM.add(new TestPass(T));

  PM.run(*M);
}

} // End of anonymous namespace.

char TestPass::ID = 0;
INITIALIZE_PASS(TestPass, "testpass", "testpass", false, false)

TEST(LiveIntervalTest, MoveUpDef) {
  // Value defined.
  DoLiveIntervalTest(
"    NOOP\n"
"    NOOP\n"
"    early-clobber %0 = IMPLICIT_DEF\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

TEST(LiveIntervalTest, MoveUpRedef) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

TEST(LiveIntervalTest, MoveUpEarlyDef) {
  DoLiveIntervalTest(
"    NOOP\n"
"    NOOP\n"
"    early-clobber %0 = IMPLICIT_DEF\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

TEST(LiveIntervalTest, MoveUpEarlyRedef) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

TEST(LiveIntervalTest, MoveUpKill) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    NOOP implicit %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

TEST(LiveIntervalTest, MoveUpKillFollowing) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    NOOP implicit %0\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 2, 1);
  });
}

// TODO: Construct a situation where we have intervals following a hole
// while still having connected components.

TEST(LiveIntervalTest, MoveDownDef) {
  // Value defined.
  DoLiveIntervalTest(
"    NOOP\n"
"    early-clobber %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

TEST(LiveIntervalTest, MoveDownRedef) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
"    NOOP\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

TEST(LiveIntervalTest, MoveDownEarlyDef) {
  DoLiveIntervalTest(
"    NOOP\n"
"    early-clobber %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

TEST(LiveIntervalTest, MoveDownEarlyRedef) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
"    NOOP\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

TEST(LiveIntervalTest, MoveDownKill) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP implicit %0\n"
"    NOOP\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

TEST(LiveIntervalTest, MoveDownKillFollowing) {
  DoLiveIntervalTest(
"    %0 = IMPLICIT_DEF\n"
"    NOOP\n"
"    NOOP implicit %0\n"
"    RETQ %0\n",
  [](MachineFunction &MF, LiveIntervals &LIS) {
    Move(MF, LIS, 1, 2);
  });
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  initLLVM();
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include "parallel.h"
#include <iostream>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include "cmdLineOptions.h"
#include "h5test.h"

void printVersion(const char* execName)
{
  if (P.myProc == 0)
    std::cerr << execName << " Version: " << H5TEST_VERSION << std::endl;
}

void printUsage(const char* execName)
{
  printVersion(execName);

  if (P.myProc == 0)
    std::cerr << "\nUsage:\n"
              << execName << " [options]\n\n"
              << "Options:\n"
              << " -h, -?        : Print Usage\n"
              << " -v            : Print Version\n"
              << " -C            : use h5 chunk\n"
              << " -S            : use h5 slab (default)\n"
              << " -N            : no T3PIO\n"
              << " -O type       : output type (l: lua, t: table, b: both (default: table))\n"
              << " -n nvar       : nvar  (default=4)\n"
              << " -l num        : local size is num (default=10)\n"
              << " -g num        : global size is num\n"
              << " -f factor     : number of stripes per writer (default=2)\n"
              << " -s num        : maximum number of stripes\n"
              << " -z num        : maximum stripe size in MB\n"
              << " -p num        : maximum number of writers per node\n"
              << " -w num        : Total number of writers\n"
              << std::endl;
}

CmdLineOptions::CmdLineOptions(int argc, char* argv[])
  : m_state(iBAD)
{
  int  opt;
  bool version, help, illegal;

  maxWritersPer  = INT_MAX;

  useT3PIO         = true;
  maxWriters       = -1;
  version          = false;
  help             = false;
  localSz          = -1;
  globalSz         = -1;
  h5chunk          = false;
  h5slab           = false;
  factor           = 1;
  stripes          = -1;
  stripeSz         = -1;
  h5style          = "h5slab";
  luaStyleOutput   = false;
  tableStyleOutput = true;

  while ( (opt = getopt(argc, argv, "s:hCSLO:f:p:w:l:g:n:z:?v")) != -1)
    {
      switch (opt)
        {
        case 'v':
          version = true;
          break;
        case '?':
        case 'h':
          help = true;
          break;
        case 'C':
          h5chunk = true;
          break;
        case 'N':
          useT3PIO = false;
          break;
        case 'f':
          factor  = strtol(optarg, (char **) NULL, 10);
          break;
        case 's':
          stripes = strtol(optarg, (char **) NULL, 10);
          break;
        case 'z':
          stripeSz = strtol(optarg, (char **) NULL, 10);
          break;
        case 'g':
          globalSz = strtoll(optarg, (char **) NULL, 10);
          break;
        case 'l':
          localSz = strtoll(optarg, (char **) NULL, 10);
          break;
        case 'n':
          nvar =    strtol(optarg, (char **) NULL, 10);
          break;
        case 'O':

          break;
        case 'p':
          maxWritersPer = strtol(optarg, (char **) NULL, 10);
          break;
        case 'w':
          maxWriters    = strtol(optarg, (char **) NULL, 10);
          break;
        case 'S':
          h5slab = true;
          break;
        default:
          illegal = true;
          ;
        }
    }

  if (version)
    {
      m_state = iHELP;
      printVersion(argv[0]);
      return;
    }

  if (help)
    {
      m_state = iHELP;
      printUsage(argv[0]);
      return;
    }

  if (! h5chunk && ! h5slab)
    h5slab = true;

  if ( h5chunk )
    h5style = "h5chunk";

  if (localSz < 0)
    {
      if (globalSz < 0)
        localSz = 10;
      else
        {
          int rem = globalSz % P.nProcs;
          localSz = globalSz/P.nProcs + (P.myProc < rem);
        }
    }

  if (globalSz < 0)
    globalSz = localSz * P.nProcs;

  m_state = iGOOD;
}

<commit_msg>better output report control with -O option<commit_after>#include "parallel.h"
#include <iostream>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include "cmdLineOptions.h"
#include "h5test.h"

void printVersion(const char* execName)
{
  if (P.myProc == 0)
    std::cerr << execName << " Version: " << H5TEST_VERSION << std::endl;
}

void printUsage(const char* execName)
{
  printVersion(execName);

  if (P.myProc == 0)
    std::cerr << "\nUsage:\n"
              << execName << " [options]\n\n"
              << "Options:\n"
              << " -h, -?        : Print Usage\n"
              << " -v            : Print Version\n"
              << " -C            : use h5 chunk\n"
              << " -S            : use h5 slab (default)\n"
              << " -N            : no T3PIO\n"
              << " -O type       : output type (l: lua, t: table, b: both (default: table))\n"
              << " -n nvar       : nvar  (default=4)\n"
              << " -l num        : local size is num (default=10)\n"
              << " -g num        : global size is num\n"
              << " -f factor     : number of stripes per writer (default=2)\n"
              << " -s num        : maximum number of stripes\n"
              << " -z num        : maximum stripe size in MB\n"
              << " -p num        : maximum number of writers per node\n"
              << " -w num        : Total number of writers\n"
              << std::endl;
}

CmdLineOptions::CmdLineOptions(int argc, char* argv[])
  : m_state(iBAD)
{
  int  opt;
  bool version, help, illegal;
  char option;

  maxWritersPer  = INT_MAX;

  useT3PIO         = true;
  maxWriters       = -1;
  version          = false;
  help             = false;
  localSz          = -1;
  globalSz         = -1;
  h5chunk          = false;
  h5slab           = false;
  factor           = 1;
  stripes          = -1;
  stripeSz         = -1;
  h5style          = "h5slab";
  luaStyleOutput   = false;
  tableStyleOutput = true;

  while ( (opt = getopt(argc, argv, "s:hCSLO:f:p:w:l:g:n:z:?v")) != -1)
    {
      switch (opt)
        {
        case 'v':
          version = true;
          break;
        case '?':
        case 'h':
          help = true;
          break;
        case 'C':
          h5chunk = true;
          break;
        case 'N':
          useT3PIO = false;
          break;
        case 'f':
          factor  = strtol(optarg, (char **) NULL, 10);
          break;
        case 's':
          stripes = strtol(optarg, (char **) NULL, 10);
          break;
        case 'z':
          stripeSz = strtol(optarg, (char **) NULL, 10);
          break;
        case 'g':
          globalSz = strtoll(optarg, (char **) NULL, 10);
          break;
        case 'l':
          localSz = strtoll(optarg, (char **) NULL, 10);
          break;
        case 'n':
          nvar =    strtol(optarg, (char **) NULL, 10);
          break;
        case 'O':
          choice         = tolower(optarg[0]);
          luaStyleOutput = ( choice == 'b' || choice == 'l')
          break;
        case 'p':
          maxWritersPer = strtol(optarg, (char **) NULL, 10);
          break;
        case 'w':
          maxWriters    = strtol(optarg, (char **) NULL, 10);
          break;
        case 'S':
          h5slab = true;
          break;
        default:
          illegal = true;
          ;
        }
    }

  if (version)
    {
      m_state = iHELP;
      printVersion(argv[0]);
      return;
    }

  if (help)
    {
      m_state = iHELP;
      printUsage(argv[0]);
      return;
    }

  if (! h5chunk && ! h5slab)
    h5slab = true;

  if ( h5chunk )
    h5style = "h5chunk";

  if (localSz < 0)
    {
      if (globalSz < 0)
        localSz = 10;
      else
        {
          int rem = globalSz % P.nProcs;
          localSz = globalSz/P.nProcs + (P.myProc < rem);
        }
    }

  if (globalSz < 0)
    globalSz = localSz * P.nProcs;

  m_state = iGOOD;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "HTTPMimeHeaderMapper.h"

//--- standard modules used ----------------------------------------------------
#include "Dbg.h"
#include "MIMEHeader.h"
#include "RE.h"
#include "AnyIterators.h"
#include "AnythingUtils.h"

//---- HTTPMimeHeaderMapper ------------------------------------------------------------------
RegisterResultMapper(HTTPMimeHeaderMapper);

HTTPMimeHeaderMapper::HTTPMimeHeaderMapper(const char *name)
	: EagerResultMapper(name)
{
	StartTrace(HTTPMimeHeaderMapper.Ctor);
}

IFAObject *HTTPMimeHeaderMapper::Clone() const
{
	return new HTTPMimeHeaderMapper(fName);
}

bool HTTPMimeHeaderMapper::DoPutStream(const char *, istream &is, Context &ctx,  ROAnything config)
{
	// Ignore key, store under Mapper.HTTPHeader by default
	StartTrace(HTTPMimeHeaderMapper.DoPutStream);
	TraceAny(config, "My Config");
	MIMEHeader::ProcessMode eProcMode = MIMEHeader::eDoSplitHeaderFields;
	if (config.IsDefined("DoNotSplitHeaderFields") && config["DoNotSplitHeaderFields"].AsBool(0) == true) {
		eProcMode = MIMEHeader::eDoNotSplitHeaderFields;
	}
	MIMEHeader mh(URLUtils::eDownshift, eProcMode);
	bool result = mh.DoReadHeader(is);

	if (result && is.good()) {
		Anything header(mh.GetInfo());
		TraceAny(header, "header");
		if (eProcMode == MIMEHeader::eDoSplitHeaderFields) {
			CorrectDateFormats(header);
		}
		//!@FIXME: all of the following should go to separate mappers
		if (config["StoreCookies"].AsLong(0)) {
			StoreCookies(header, ctx);
		}
		if (config.IsDefined("Suppress")) {
			ROAnything suppresslist(config["Suppress"]);
			SuppressHeaders(header, suppresslist);
		}
		if (config.IsDefined("Add")) {
			ROAnything addlist(config["Add"]);
			AddHeaders(header, addlist);
		}
		if (config.IsDefined("Substitute")) {
			ROAnything addlist(config["Substitute"]);
			Substitute(header, addlist, ctx);
		}
		//!@FIXME: here we should use Put()/DoPutAny() to allow further processing of header data before storing
		result = DoFinalPutAny("HTTPHeader", header, ctx);
	}
	return result && is.good();
}

void HTTPMimeHeaderMapper::CorrectDateFormats(Anything &header)
{
	// we assume to-lower keys
	const char *keylist[] = {
		"if-modified-since",
		"if-range",
		"if-unmodified-since",
		"last-modified",
		"retry-after",
		"date",
		"expires"
	};
	for (int i = 0; i < (int)(sizeof(keylist) / sizeof(keylist[0])); ++i) {
		const char *key = keylist[i];
		if (header.IsDefined(key) && header[key].GetType() == AnyArrayType) {
			String newvalue;
			Anything oldvalue(header[key]);
			for (long j = 0L, sz = oldvalue.GetSize(); j < sz; ++j) {
				if (newvalue.Length() > 0) {
					newvalue.Append(", ");
				}
				newvalue.Append(oldvalue[j].AsString());
			}
			header[key] = newvalue;
		}
	}
}

void HTTPMimeHeaderMapper::SuppressHeaders(Anything &header, ROAnything &suppresslist)
{
	for (long i = 0, sz = suppresslist.GetSize(); i < sz; ++i) {
		String keytosuppress = suppresslist[i].AsCharPtr();
		keytosuppress.ToLower();
		if (header.IsDefined(keytosuppress)) {
			header.Remove(keytosuppress);
		}
	}
}

void HTTPMimeHeaderMapper::AddHeaders(Anything &header, ROAnything &addlist)
{
	for (long i = 0, sz = addlist.GetSize(); i < sz; ++i) {
		String key(addlist.SlotName(i));
		String hdr(addlist[i].AsString());
		// normalize key to lower-type (header info stays as is)
		key.ToLower();
		// overwrite, if existing
		header[key] = hdr;
	}
}

void HTTPMimeHeaderMapper::Substitute(Anything &header, ROAnything &addlist, Context &ctx)
{
	StartTrace(HTTPMimeHeaderMapper.Substitute);

	TraceAny(ctx.GetQuery(), "query:");

	String key;
	String pattern;
	String replacement;
	String slotName = addlist.SlotName(0);
	if (slotName.Length() > 0) {
		key = addlist["Key"].AsString();
		pattern = addlist["Pattern"].AsString();
		replacement = addlist["Replacement"].AsString();
		RE substRegex(pattern, RE::MATCH_ICASE);
		for (int i = 0; i < header.GetSize(); i++) {
			if (header.SlotName(i) == key) {
				header[i] = substRegex.Subst(header[i].AsString(), replacement);
			}
		}
	} else {
		for (int i = 0; i < addlist.GetSize(); i++) {
			key = addlist[i]["Key"].AsString();
			pattern = addlist[i]["Pattern"].AsString();
			replacement = addlist[i]["Replacement"].AsString();

			RE substRegex(pattern, RE::MATCH_ICASE);
			for (int j = 0; j < header.GetSize(); j++) {
				if (header.SlotName(j) == key) {
					header[j] = substRegex.Subst(header[j].AsString(), replacement);
				}
			}
		}
	}
}

void HTTPMimeHeaderMapper::StoreCookies(ROAnything const header, Context &ctx) {
	StartTrace(HTTPMimeHeaderMapper.StoreCookies);

	const String valueSlotName("_value_");
	const String attrSlotName("_attrs_");
	const String cookieID("set-cookie");
	const char cookieEnd = ';';
	String strKeyValue(64L), strCookie(128L), strKey(32L), strValue(64L);
	Anything anyCookies;
	ROAnything roaCookie;
	AnyExtensions::Iterator<ROAnything> cookieIterator(header[cookieID]);
	while ( cookieIterator.Next(roaCookie) ) {
		TraceAny(roaCookie, "current cookie entry");
		strCookie = roaCookie.AsString();
		String cookieName(32L);
		StringTokenizer semiTokenizer(strCookie, cookieEnd);
		Anything anyNamedCookie;
		while ( semiTokenizer.NextToken(strKeyValue) ) {
			StringTokenizer valueTokenizer(strKeyValue, '=');
			if ( valueTokenizer.NextToken(strKey) ) {
				strKey.TrimWhitespace();
				strValue = valueTokenizer.GetRemainder();
				if ( !cookieName.Length() ) {
					cookieName = strKey;
					if ( strValue.Length() ) {
						anyNamedCookie[valueSlotName] = strValue;
					}
				} else {
					if ( strValue.Length() ) {
						anyNamedCookie[attrSlotName][strKey] = strValue;
					} else {
						anyNamedCookie[attrSlotName].Append(strKey);
					}
				}
			}
		}
		if ( anyNamedCookie.GetSize() > 0 && cookieName.Length() ) {
			anyCookies[cookieName].Append(anyNamedCookie);
		}
	}
	//!@FIXME: this part should be factored out into separate mapper
	String destSlotname("StoredCookies.");
	const String backendName(ctx.Lookup("Backend.Name", ""));
	destSlotname.Append(backendName);
	if ( anyCookies.GetSize() > 0 ) {
		TraceAny(anyCookies, "prepared cookie values");
		String plainCookieString(256L), cookieName(32L);
		AnyExtensions::Iterator<ROAnything> structureIter(anyCookies);
		ROAnything roaEntry;
		while ( structureIter.Next(roaEntry) ) {
			if (!plainCookieString.Length()) {
				plainCookieString.Append("Cookie:");
			}
			structureIter.SlotName(cookieName);
			//!@FIXME: in future we should decide on attributes to select correct value entry to use, currently we use the last one (roaEntry.GetSize()-1) if multiple entries exist
			plainCookieString.Append(' ').Append(cookieName).Append('=').Append(roaEntry[roaEntry.GetSize()-1][valueSlotName].AsString()).Append(cookieEnd);
		}
		Anything anyPlainString(plainCookieString);
		StorePutter::Operate(anyPlainString, ctx, "Session", String(destSlotname).Append(".Plain"));
		StorePutter::Operate(anyCookies, ctx, "Session", String(destSlotname).Append(".Structured"));
	}
	TraceAny(ctx.Lookup("StoredCookies"), "cookies from context");
}
<commit_msg>corrected cookie handling; new cookies will be appended to existing ones<commit_after>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "HTTPMimeHeaderMapper.h"

//--- standard modules used ----------------------------------------------------
#include "Dbg.h"
#include "MIMEHeader.h"
#include "RE.h"
#include "AnyIterators.h"
#include "AnythingUtils.h"

//---- HTTPMimeHeaderMapper ------------------------------------------------------------------
RegisterResultMapper(HTTPMimeHeaderMapper);

HTTPMimeHeaderMapper::HTTPMimeHeaderMapper(const char *name)
	: EagerResultMapper(name)
{
	StartTrace(HTTPMimeHeaderMapper.Ctor);
}

IFAObject *HTTPMimeHeaderMapper::Clone() const
{
	return new HTTPMimeHeaderMapper(fName);
}

bool HTTPMimeHeaderMapper::DoPutStream(const char *, istream &is, Context &ctx,  ROAnything config)
{
	// Ignore key, store under Mapper.HTTPHeader by default
	StartTrace(HTTPMimeHeaderMapper.DoPutStream);
	TraceAny(config, "My Config");
	MIMEHeader::ProcessMode eProcMode = MIMEHeader::eDoSplitHeaderFields;
	if (config.IsDefined("DoNotSplitHeaderFields") && config["DoNotSplitHeaderFields"].AsBool(0) == true) {
		eProcMode = MIMEHeader::eDoNotSplitHeaderFields;
	}
	MIMEHeader mh(URLUtils::eDownshift, eProcMode);
	bool result = mh.DoReadHeader(is);

	if (result && is.good()) {
		Anything header(mh.GetInfo());
		TraceAny(header, "header");
		if (eProcMode == MIMEHeader::eDoSplitHeaderFields) {
			CorrectDateFormats(header);
		}
		//!@FIXME: all of the following should go to separate mappers
		if (config["StoreCookies"].AsLong(0)) {
			StoreCookies(header, ctx);
		}
		if (config.IsDefined("Suppress")) {
			ROAnything suppresslist(config["Suppress"]);
			SuppressHeaders(header, suppresslist);
		}
		if (config.IsDefined("Add")) {
			ROAnything addlist(config["Add"]);
			AddHeaders(header, addlist);
		}
		if (config.IsDefined("Substitute")) {
			ROAnything addlist(config["Substitute"]);
			Substitute(header, addlist, ctx);
		}
		//!@FIXME: here we should use Put()/DoPutAny() to allow further processing of header data before storing
		result = DoFinalPutAny("HTTPHeader", header, ctx);
	}
	return result && is.good();
}

void HTTPMimeHeaderMapper::CorrectDateFormats(Anything &header)
{
	// we assume to-lower keys
	const char *keylist[] = {
		"if-modified-since",
		"if-range",
		"if-unmodified-since",
		"last-modified",
		"retry-after",
		"date",
		"expires"
	};
	for (int i = 0; i < (int)(sizeof(keylist) / sizeof(keylist[0])); ++i) {
		const char *key = keylist[i];
		if (header.IsDefined(key) && header[key].GetType() == AnyArrayType) {
			String newvalue;
			Anything oldvalue(header[key]);
			for (long j = 0L, sz = oldvalue.GetSize(); j < sz; ++j) {
				if (newvalue.Length() > 0) {
					newvalue.Append(", ");
				}
				newvalue.Append(oldvalue[j].AsString());
			}
			header[key] = newvalue;
		}
	}
}

void HTTPMimeHeaderMapper::SuppressHeaders(Anything &header, ROAnything &suppresslist)
{
	for (long i = 0, sz = suppresslist.GetSize(); i < sz; ++i) {
		String keytosuppress = suppresslist[i].AsCharPtr();
		keytosuppress.ToLower();
		if (header.IsDefined(keytosuppress)) {
			header.Remove(keytosuppress);
		}
	}
}

void HTTPMimeHeaderMapper::AddHeaders(Anything &header, ROAnything &addlist)
{
	for (long i = 0, sz = addlist.GetSize(); i < sz; ++i) {
		String key(addlist.SlotName(i));
		String hdr(addlist[i].AsString());
		// normalize key to lower-type (header info stays as is)
		key.ToLower();
		// overwrite, if existing
		header[key] = hdr;
	}
}

void HTTPMimeHeaderMapper::Substitute(Anything &header, ROAnything &addlist, Context &ctx)
{
	StartTrace(HTTPMimeHeaderMapper.Substitute);

	TraceAny(ctx.GetQuery(), "query:");

	String key;
	String pattern;
	String replacement;
	String slotName = addlist.SlotName(0);
	if (slotName.Length() > 0) {
		key = addlist["Key"].AsString();
		pattern = addlist["Pattern"].AsString();
		replacement = addlist["Replacement"].AsString();
		RE substRegex(pattern, RE::MATCH_ICASE);
		for (int i = 0; i < header.GetSize(); i++) {
			if (header.SlotName(i) == key) {
				header[i] = substRegex.Subst(header[i].AsString(), replacement);
			}
		}
	} else {
		for (int i = 0; i < addlist.GetSize(); i++) {
			key = addlist[i]["Key"].AsString();
			pattern = addlist[i]["Pattern"].AsString();
			replacement = addlist[i]["Replacement"].AsString();

			RE substRegex(pattern, RE::MATCH_ICASE);
			for (int j = 0; j < header.GetSize(); j++) {
				if (header.SlotName(j) == key) {
					header[j] = substRegex.Subst(header[j].AsString(), replacement);
				}
			}
		}
	}
}

void HTTPMimeHeaderMapper::StoreCookies(ROAnything const header, Context &ctx) {
	StartTrace(HTTPMimeHeaderMapper.StoreCookies);

	const String valueSlotName("_value_");
	const String attrSlotName("_attrs_");
	const String cookieID("set-cookie");
	const char cookieEnd = ';';
	String destSlotname("StoredCookies.");
	const String backendName(ctx.Lookup("Backend.Name", ""));
	destSlotname.Append(backendName);

	String strKeyValue(64L), strCookie(128L), strKey(32L), strValue(64L);
	ROAnything roaCookie;
	AnyExtensions::Iterator<ROAnything> cookieIterator(header[cookieID]);
	while ( cookieIterator.Next(roaCookie) ) {
		TraceAny(roaCookie, "current cookie entry");
		strCookie = roaCookie.AsString();
		String cookieName(32L);
		StringTokenizer semiTokenizer(strCookie, cookieEnd);
		Anything anyNamedCookie;
		while ( semiTokenizer.NextToken(strKeyValue) ) {
			StringTokenizer valueTokenizer(strKeyValue, '=');
			if ( valueTokenizer.NextToken(strKey) ) {
				strKey.TrimWhitespace();
				strValue = valueTokenizer.GetRemainder();
				if ( !cookieName.Length() ) {
					cookieName = strKey;
					if ( strValue.Length() ) {
						anyNamedCookie[valueSlotName] = strValue;
					}
				} else {
					if ( strValue.Length() ) {
						anyNamedCookie[attrSlotName][strKey] = strValue;
					} else {
						anyNamedCookie[attrSlotName].Append(strKey);
					}
				}
			}
		}
		if ( anyNamedCookie.GetSize() > 0 && cookieName.Length() ) {
			String strStructured(destSlotname);
			strStructured.Append(".Structured.").Append(cookieName);
			TraceAny(anyNamedCookie, "storing named cookie at [" << strStructured << "]");
			StorePutter::Operate(anyNamedCookie, ctx, "Session", strStructured);
		}
	}
	//!@FIXME: this part should be factored out into separate mapper
	ROAnything anyCookies = ctx.Lookup(String(destSlotname).Append(".Structured"));
	if ( anyCookies.GetSize() > 0 ) {
		TraceAny(anyCookies, "prepared cookie values");
		String plainCookieString(256L), cookieName(32L);
		AnyExtensions::Iterator<ROAnything> structureIter(anyCookies);
		ROAnything roaEntry;
		while ( structureIter.Next(roaEntry) ) {
			if (!plainCookieString.Length()) {
				plainCookieString.Append("Cookie:");
			}
			structureIter.SlotName(cookieName);
			//!@FIXME: in future we should decide on attributes to select correct value entry to use, currently we use the last one (roaEntry.GetSize()-1) if multiple entries exist
			plainCookieString.Append(' ').Append(cookieName).Append('=').Append(roaEntry[roaEntry.GetSize()-1][valueSlotName].AsString()).Append(cookieEnd);
		}
		Anything anyPlainString(plainCookieString);
		Trace("plain cookie string [" << plainCookieString << "]");
		StorePutter::Operate(anyPlainString, ctx, "Session", String(destSlotname).Append(".Plain"));
	}
	TraceAny(ctx.Lookup("StoredCookies"), "cookies from context");
}
<|endoftext|>


<commit_before>//      © Christian Sommerfeldt Øien
//      All rights reserved
#include "musicm.hpp"

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <array>

#define SR 44100

const double pi = 3.141592653589;
double rnd(double a, double b) { return a + rand() * (b - a) / RAND_MAX; }
double sine(double x) { return sin(x * 2 * pi); }
double linear(double a, double b, double r) { return a * (1 - r) + b * r; }

struct lfo
{
    double d, x;

    lfo(double d = 0) : d(d), x(rnd(0, 1)) {}

    double y()
    {
        if ((x += d) > 1) x -= 1;
        return sine(x);
    }

    double linear(double a, double b)
    {
        return ::linear(a, b, .5 * (1 + y()));
    }
};

struct ring_buffer
{
    std::vector<float> samples;
    unsigned i;

    ring_buffer(unsigned n) : samples(n), i()
    {}

    void ring_walk()
    {
        if (i == 0) i = samples.size();
        --i;
    }

    float & element(unsigned k = 0)
    {
        return samples[(i + k) % samples.size()];
    }
};

struct worm_buffer : ring_buffer
{
    lfo delay;
    unsigned n;
    unsigned n_target;
    double step_progress;
    double step_speed;

    worm_buffer(unsigned n = 0)
        : ring_buffer(SR/10)
        , n(n)
        , n_target(n)
        , step_progress()
        , step_speed(.01)
    {}

    void grow()
    {
        if (n == 0) {
            n = n_target;
            return;
        }

        if (n_target != n) {
            step_progress += step_speed;
            if (step_progress >= 1) {
                step_progress = 0;
                if (n_target > n) n += 1;
                else n -= 1;
            }
        }
    }

};

struct va_karpluss : worm_buffer
{
    void excite()
    {
        const double y = rnd(.8, 1);
        for (size_t k=1; k<n; k++)
            element(k) += rnd(-y, y);
    }

    double shift()
    {
        grow();

        const unsigned k = n * linear(.99, .999, .5 * (1 + delay.y()));
        const double r = .99 * linear(element(k - 1), element(k), .8);
        element() = r;
        ring_walk();
        return r;
    }
};

struct va_comb : worm_buffer
{
    lfo fundamental;
    va_comb() : fundamental(.4/SR) {}
    double shift(double v) {
        n_target = SR/fundamental.linear(48, 880);
        grow();

        const double r = linear(v, element(n), .3);
        element() = v;
        ring_walk();
        return r;
    }
};

class biquad
{
    double w1, w2;
public:
    double a1, a2, b0, b1, b2;

    biquad() : w1(), w2(), a1(), a2(), b0(), b1(), b2() {}

    double shift(double x)
    {
        const double w0 = x - a1 * w1 - a2 * w2;
        const double y = b0 * w0 + b1 * w1 + b2 * w2;
        w2 = w1;
        w1 = w0;
        return y;
    }

    void set_wah(double c, double q)
    {
      const double p = 2 * pi * c / SR;
      const double alpha = sin(p) / (2 * q);
      const double a0 = 1 + alpha;
      a1 = (-2 * cos(p)) / a0;
      a2 = (1 - alpha) / a0;
      b0 = alpha / a0;
      b2 = -b0;
    }
};

struct wah_wah
{
    biquad f;
    lfo pedal;
    lfo mix;

    wah_wah() : pedal(.9/SR), mix(3.1/SR) {}

    double shift(double v)
    {
        double c = pedal.linear(36, 880);
        f.set_wah(c, .98);
        return linear(v, f.shift(v),
                mix.linear(.5, .6));
    }
};

struct echo
{
    double a;
    lfo delay;
    unsigned cached_d;
    echo(double a) : a(a), cached_d() {}
};

struct reverbr : ring_buffer
{
    std::vector<echo> echoes;
    reverbr() : ring_buffer(SR)
    {
        for (unsigned k=0; k<9; k++) {
            echo e(rnd(.01, .03));
            e.delay.d = rnd(.1, 1)/SR;
            echoes.push_back(e);
        }
    }

    void move_echoes()
    {
        for (unsigned k=0; k<echoes.size(); k++) {
            echo & e = echoes[k];
            e.cached_d = linear(1, samples.size(),
                        .5 * (1 + e.delay.y()));
        }
    }

    double get()
    {
        static unsigned c = 0;
        if (c) --c;
        else {
            c = 441;
            move_echoes();
        }
        double r = 0;
        for (unsigned k=0; k<echoes.size(); k++) {
            const echo & e = echoes[k];
            r += e.a * element(e.cached_d);
        }
        return r;
    }

    void put(double v)
    {
        element() = v;
    }
};

struct recorder
{
    reverbr re;
    wah_wah wa;
    wah_wah wb;
    va_comb cb;

    void put(double v)
    {
        v = wa.shift(v);
        v = wb.shift(v);
        v = cb.shift(v);
        v += re.get();
        re.put(v);

        if (v > 1) v = 1;
        else if (v < -1) v = -1;
        int16_t b = v * 32767;
        // on-need: swap bytes if be arch (detect in constructor)
        fwrite(&b, 2, 1, stdout);
    }
};

struct arp_wire
{
    va_karpluss buf;
    unsigned c_touch;

    arp_wire() : c_touch() {}

    void move(double pitch)
    {
        buf.n_target = SR / f_of_just(pitch);
    }

    void touch()
    {
        c_touch += std::floor(rnd(2, 8)) * SR/4;
        buf.excite();
    }

    double get(unsigned c)
    {
        if (c > c_touch) touch();
        return buf.shift();
    }
};

struct arp_digitar
{
    static const unsigned n_wires = 6;
    arp_wire wires[n_wires];
    using chord = std::array<unsigned, n_wires>;

    void draw(chord pitches)
    {
        const unsigned p = 36;
        wires[5].move(pitches[0] + p + 4);
        wires[4].move(pitches[1] + p + 9);
        wires[3].move(pitches[2] + p + 14);
        wires[2].move(pitches[3] + p + 19);
        wires[1].move(pitches[4] + p + 23);
        wires[0].move(pitches[5] + p + 28);
    }

    double get(unsigned c)
    {
        double r = 0;
        for (unsigned i=0; i<n_wires; ++i)
            r += wires[i].get(c + (1 + i)*SR/64);
        return r / n_wires;
    }
};

std::vector<arp_digitar::chord> score = {
    { 0, 0, 2, 2, 2, 0 }, //A
    { 0, 2, 2, 1, 0, 0 }, //E
    { 0, 0, 0, 2, 3, 2 }, //D

    { 0, 0, 2, 2, 1, 0 }, //Am
    { 0, 2, 2, 1, 0, 0 }, //E
    { 1, 0, 0, 2, 3, 1 }, //Dm

    { 0, 2, 2, 1, 0, 0 }, //E
    { 2, 2, 1, 2, 0, 2 }, //B7
    { 0, 0, 2, 2, 2, 0 }, //A

    { 0, 2, 2, 0, 0, 0 }, //Em
    { 2, 2, 1, 2, 0, 2 }, //B7
    { 0, 0, 2, 2, 1, 0 }, //Am

    { 0, 0, 0, 2, 3, 2 }, //D
    { 0, 0, 2, 0, 2, 0 }, //A7
    { 3, 2, 0, 0, 0, 3 }, //G

    { 1, 0, 0, 2, 3, 1 }, //Dm
    { 0, 0, 2, 2, 2, 0 }, //A
    { 3, 0, 0, 3, 3, 3 }, //Gm

    { 3, 2, 0, 0, 0, 3 }, //G
    { 0, 0, 0, 2, 1, 2 }, //D7
    { 0, 3, 2, 0, 1, 0 }, //C

    { 0, 3, 2, 0, 1, 0 }, //C
    { 3, 2, 0, 0, 0, 1 }, //G7
    { 0, 3, 3, 2, 1, 1 }, //F
};

extern "C" int isatty(int);

int main()
{
    if (isatty(1)) {
        fprintf(stderr, "redirect stdout and i'll write 1ch 16/le audio\n");
        return 1;
    }
    unsigned i = 0;
    arp_digitar aw;
    recorder rec;
    for (std::size_t c=0; c<SR*48; c++) {
        if (c % (2*SR) == 0)
            aw.draw(score[i++ % score.size()]);
        rec.put(aw.get(c));
    }
}

<commit_msg>disabled strings in chords<commit_after>//      © Christian Sommerfeldt Øien
//      All rights reserved
#include "musicm.hpp"

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <array>

#define SR 44100

const double pi = 3.141592653589;
double rnd(double a, double b) { return a + rand() * (b - a) / RAND_MAX; }
double sine(double x) { return sin(x * 2 * pi); }
double linear(double a, double b, double r) { return a * (1 - r) + b * r; }

struct lfo
{
    double d, x;

    lfo(double d = 0) : d(d), x(rnd(0, 1)) {}

    double y()
    {
        if ((x += d) > 1) x -= 1;
        return sine(x);
    }

    double linear(double a, double b)
    {
        return ::linear(a, b, .5 * (1 + y()));
    }
};

struct ring_buffer
{
    std::vector<float> samples;
    unsigned i;

    ring_buffer(unsigned n) : samples(n), i()
    {}

    void ring_walk()
    {
        if (i == 0) i = samples.size();
        --i;
    }

    float & element(unsigned k = 0)
    {
        return samples[(i + k) % samples.size()];
    }
};

struct worm_buffer : ring_buffer
{
    lfo delay;
    unsigned n;
    unsigned n_target;
    double step_progress;
    double step_speed;

    worm_buffer(unsigned n = 0)
        : ring_buffer(SR/10)
        , n(n)
        , n_target(n)
        , step_progress()
        , step_speed(.01)
    {}

    void grow()
    {
        if (n == 0) {
            n = n_target;
            return;
        }

        if (n_target != n) {
            step_progress += step_speed;
            if (step_progress >= 1) {
                step_progress = 0;
                if (n_target > n) n += 1;
                else n -= 1;
            }
        }
    }

};

struct va_karpluss : worm_buffer
{
    void excite()
    {
        const double y = rnd(.8, 1);
        for (size_t k=1; k<n; k++)
            element(k) += rnd(-y, y);
    }

    double shift()
    {
        grow();

        const unsigned k = n * linear(.99, .999, .5 * (1 + delay.y()));
        const double r = .99 * linear(element(k - 1), element(k), .8);
        element() = r;
        ring_walk();
        return r;
    }
};

struct va_comb : worm_buffer
{
    lfo fundamental;
    va_comb() : fundamental(.4/SR) {}
    double shift(double v) {
        n_target = SR/fundamental.linear(48, 880);
        grow();

        const double r = linear(v, element(n), .3);
        element() = v;
        ring_walk();
        return r;
    }
};

class biquad
{
    double w1, w2;
public:
    double a1, a2, b0, b1, b2;

    biquad() : w1(), w2(), a1(), a2(), b0(), b1(), b2() {}

    double shift(double x)
    {
        const double w0 = x - a1 * w1 - a2 * w2;
        const double y = b0 * w0 + b1 * w1 + b2 * w2;
        w2 = w1;
        w1 = w0;
        return y;
    }

    void set_wah(double c, double q)
    {
      const double p = 2 * pi * c / SR;
      const double alpha = sin(p) / (2 * q);
      const double a0 = 1 + alpha;
      a1 = (-2 * cos(p)) / a0;
      a2 = (1 - alpha) / a0;
      b0 = alpha / a0;
      b2 = -b0;
    }
};

struct wah_wah
{
    biquad f;
    lfo pedal;
    lfo mix;

    wah_wah() : pedal(9/SR), mix(31/SR) {}

    double shift(double v)
    {
        double c = pedal.linear(36, 880);
        f.set_wah(c, .98);
        return linear(v, f.shift(v),
                mix.linear(.5, .6));
    }
};

struct echo
{
    double a;
    lfo delay;
    unsigned cached_d;
    echo(double a) : a(a), cached_d() {}
};

struct reverbr : ring_buffer
{
    std::vector<echo> echoes;
    reverbr() : ring_buffer(SR)
    {
        for (unsigned k=0; k<9; k++) {
            echo e(rnd(.01, .03));
            e.delay.d = rnd(.1, 1)/SR;
            echoes.push_back(e);
        }
    }

    void move_echoes()
    {
        for (unsigned k=0; k<echoes.size(); k++) {
            echo & e = echoes[k];
            e.cached_d = linear(1, samples.size(),
                        .5 * (1 + e.delay.y()));
        }
    }

    double get()
    {
        static unsigned c = 0;
        if (c) --c;
        else {
            c = 441;
            move_echoes();
        }
        double r = 0;
        for (unsigned k=0; k<echoes.size(); k++) {
            const echo & e = echoes[k];
            r += e.a * element(e.cached_d);
        }
        return r;
    }

    void put(double v)
    {
        element() = v;
    }
};

struct recorder
{
    reverbr re;
    wah_wah wa;
    wah_wah wb;
    va_comb cb;

    void put(double v)
    {
        v = wa.shift(v);
        v = wb.shift(v);
        v = cb.shift(v);
        v += re.get();
        re.put(v);

        if (v > 1) v = 1;
        else if (v < -1) v = -1;
        int16_t b = v * 32767;
        // on-need: swap bytes if be arch (detect in constructor)
        fwrite(&b, 2, 1, stdout);
    }
};

struct arp_wire
{
    va_karpluss buf;
    unsigned c_touch;
    bool enabled;

    arp_wire() : c_touch(), enabled() {}

    void move(double pitch)
    {
        buf.n_target = SR / f_of_just(pitch);
    }

    void touch()
    {
        c_touch += std::floor(rnd(1, 4)) * SR/8;
        if (enabled) buf.excite();
    }

    double get(unsigned c)
    {
        if (c > c_touch) touch();
        return buf.shift();
    }
};

struct arp_digitar
{
    static const unsigned n_wires = 6;
    arp_wire wires[n_wires];
    using chord = std::array<int, n_wires>;

    void draw(chord pitches)
    {
        constexpr unsigned p = 36;
        constexpr unsigned a[] = {
            p + 4, p + 9,
            p + 14, p + 19,
            p + 23, p + 28 };

        for (unsigned i=0; i<n_wires; i++) {
            arp_wire & w = wires[n_wires - 1 - i];
            if (pitches[i] >= 0) {
                w.enabled = true;
                w.move(a[i] + pitches[i]);
            } else {
                w.enabled = false;
                w.move(a[i]);
            }
        }
    }

    double get(unsigned c)
    {
        double r = 0;
        for (unsigned i=0; i<n_wires; ++i)
            r += wires[i].get(c);
        return r / n_wires;
    }
};

constexpr int X = -1;

std::vector<arp_digitar::chord> score = {
    { X, X, X, X, X, X },

    { X, 0, 2, 2, 2, 0 }, //A
    { 0, 2, 2, 1, 0, 0 }, //E
    { X, X, 0, 2, 3, 2 }, //D

    { X, 0, 2, 2, 1, 0 }, //Am
    { 0, 2, 2, 1, 0, 0 }, //E
    { X, X, 0, 2, 3, 1 }, //Dm

    { 0, 2, 2, 1, 0, 0 }, //E
    { X, 2, 1, 2, 0, 2 }, //B7
    { X, 0, 2, 2, 2, 0 }, //A

    { 0, 2, 2, 0, 0, 0 }, //Em
    { X, 2, 1, 2, 0, 2 }, //B7
    { X, 0, 2, 2, 1, 0 }, //Am

    { X, X, 0, 2, 3, 2 }, //D
    { X, 0, 2, 0, 2, 0 }, //A7
    { 3, 2, 0, 0, 0, 3 }, //G

    { X, X, 0, 2, 3, 1 }, //Dm
    { X, 0, 2, 2, 2, 0 }, //A
    { 3, 0, 0, 3, 3, 3 }, //Gm

    { 3, 2, 0, 0, 0, 3 }, //G
    { X, X, 0, 2, 1, 2 }, //D7
    { X, 3, 2, 0, 1, 0 }, //C

    { X, 3, 2, 0, 1, 0 }, //C
    { 3, 2, 0, 0, 0, 1 }, //G7
    { X, X, 3, 2, 1, 1 }, //F

    { X, X, X, X, X, X },
    { X, X, X, X, X, X },
};

extern "C" int isatty(int);

int main()
{
    if (isatty(1)) {
        fprintf(stderr, "redirect stdout and i'll write 1ch 16/le audio\n");
        return 1;
    }
    arp_digitar aw;
    recorder rec;
    unsigned i = 0;
    unsigned c = 0;
    constexpr unsigned r = SR * 4;
    while (true) {
        if (c % r == 0) {
            if (i == score.size()) break;
            aw.draw(score[i++]);
        }
        rec.put(aw.get(c++));
    }
}

<|endoftext|>


<commit_before>//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//

#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

void CodeEmitterGen::emitInstrOpBits(std::ostream &o,
                                     const std::vector<RecordVal> &Vals,
                                     std::map<std::string, unsigned> &OpOrder,
                                     std::map<std::string, bool> &OpContinuous)
{
  for (unsigned f = 0, e = Vals.size(); f != e; ++f) {
    if (Vals[f].getPrefix()) {
      BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();

      // Scan through the field looking for bit initializers of the current
      // variable...
      for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) {
        Init *I = FieldInitializer->getBit(i);
        if (BitInit *BI = dynamic_cast<BitInit*>(I)) {
          DEBUG(o << "      // bit init: f: " << f << ", i: " << i << "\n");
        } else if (UnsetInit *UI = dynamic_cast<UnsetInit*>(I)) {
          DEBUG(o << "      // unset init: f: " << f << ", i: " << i << "\n");
        } else if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(I)) {
          TypedInit *TI = VBI->getVariable();
          if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
            // If the bits of the field are laid out consecutively in the
            // instruction, then instead of separately ORing in bits, just
            // mask and shift the entire field for efficiency.
            if (OpContinuous[VI->getName()]) {
              // already taken care of in the loop above, thus there is no
              // need to individually OR in the bits

              // for debugging, output the regular version anyway, commented
              DEBUG(o << "      // Value |= getValueBit(op"
                      << OpOrder[VI->getName()] << ", " << VBI->getBitNum()
                      << ")" << " << " << i << ";\n");
            } else {
              o << "      Value |= getValueBit(op" << OpOrder[VI->getName()]
                << ", " << VBI->getBitNum()
                << ")" << " << " << i << ";\n";
            }
          } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
            // FIXME: implement this!
            std::cerr << "Error: FieldInit not implemented!\n";
            abort();
          } else {
            std::cerr << "Error: unimplemented case in "
                      << "CodeEmitterGen::emitInstrOpBits()\n";
            abort();
          }
        }
      }
    }
  }
}

void CodeEmitterGen::run(std::ostream &o) {
  CodeGenTarget Target;
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  EmitSourceFileHeader("Machine Code Emitter", o);
  o << "namespace llvm {\n\n";
  std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";

  // Emit function declaration
  o << "unsigned " << Target.getName() << "CodeEmitter::"
    << "getBinaryCodeForInstr(MachineInstr &MI) {\n"
    << "  unsigned Value = 0;\n"
    << "  DEBUG(std::cerr << MI);\n"
    << "  switch (MI.getOpcode()) {\n";

  // Emit a case statement for each opcode
  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
       I != E; ++I) {
    Record *R = *I;
    o << "    case " << Namespace << R->getName() << ": {\n"
      << "      DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n";

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    // For little-endian instruction bit encodings, reverse the bit order
    if (Target.isLittleEndianEncoding()) {
      unsigned numBits = BI->getNumBits();
      BitsInit *NewBI = new BitsInit(numBits);
      for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
        unsigned bitSwapIdx = numBits - bit - 1;
        Init *OrigBit = BI->getBit(bit);
        Init *BitSwap = BI->getBit(bitSwapIdx);
        NewBI->setBit(bit, BitSwap);
        NewBI->setBit(bitSwapIdx, OrigBit);
      }
      if (numBits % 2) {
        unsigned middle = (numBits + 1) / 2;
        NewBI->setBit(middle, BI->getBit(middle));
      }
      BI = NewBI;
    }

    unsigned Value = 0;
    const std::vector<RecordVal> &Vals = R->getValues();

    DEBUG(o << "      // prefilling: ");
    // Start by filling in fixed values...
    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
      if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
        Value |= B->getValue() << (e-i-1);
        DEBUG(o << B->getValue());
      } else {
        DEBUG(o << "0");
      }
    }
    DEBUG(o << "\n");

    DEBUG(o << "      // " << *R->getValue("Inst") << "\n");
    o << "      Value = " << Value << "U;\n\n";

    // Loop over all of the fields in the instruction, determining which are the
    // operands to the instruction.
    unsigned op = 0;
    std::map<std::string, unsigned> OpOrder;
    std::map<std::string, bool> OpContinuous;
    for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
      if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
        // Is the operand continuous? If so, we can just mask and OR it in
        // instead of doing it bit-by-bit, saving a lot in runtime cost.
        BitsInit *InstInit = BI;
        int beginBitInVar = -1, endBitInVar = -1;
        int beginBitInInst = -1, endBitInInst = -1;
        bool continuous = true;

        for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) {
          if (VarBitInit *VBI =
              dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) {
            TypedInit *TI = VBI->getVariable();
            if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
              // only process the current variable
              if (VI->getName() != Vals[i].getName())
                continue;

              if (beginBitInVar == -1)
                beginBitInVar = VBI->getBitNum();

              if (endBitInVar == -1)
                endBitInVar = VBI->getBitNum();
              else {
                if (endBitInVar == (int)VBI->getBitNum() + 1)
                  endBitInVar = VBI->getBitNum();
                else {
                  continuous = false;
                  break;
                }
              }

              if (beginBitInInst == -1)
                beginBitInInst = bit;
              if (endBitInInst == -1)
                endBitInInst = bit;
              else {
                if (endBitInInst == bit + 1)
                  endBitInInst = bit;
                else {
                  continuous = false;
                  break;
                }
              }

              // maintain same distance between bits in field and bits in
              // instruction. if the relative distances stay the same
              // throughout,
              if (beginBitInVar - (int)VBI->getBitNum() !=
                  beginBitInInst - bit) {
                continuous = false;
                break;
              }
            }
          }
        }

        // If we have found no bit in "Inst" which comes from this field, then
        // this is not an operand!!
        if (beginBitInInst != -1) {
          o << "      // op" << op << ": " << Vals[i].getName() << "\n"
            << "      int64_t op" << op
            <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n";
          //<< "   MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n";
          OpOrder[Vals[i].getName()] = op++;

          DEBUG(o << "      // Var: begin = " << beginBitInVar
                  << ", end = " << endBitInVar
                  << "; Inst: begin = " << beginBitInInst
                  << ", end = " << endBitInInst << "\n");

          if (continuous) {
            DEBUG(o << "      // continuous: op" << OpOrder[Vals[i].getName()]
                    << "\n");

            // Mask off the right bits
            // Low mask (ie. shift, if necessary)
            assert(endBitInVar >= 0 && "Negative shift amount in masking!");
            if (endBitInVar != 0) {
              o << "      op" << OpOrder[Vals[i].getName()]
                << " >>= " << endBitInVar << ";\n";
              beginBitInVar -= endBitInVar;
              endBitInVar = 0;
            }

            // High mask
            o << "      op" << OpOrder[Vals[i].getName()]
              << " &= (1<<" << beginBitInVar+1 << ") - 1;\n";

            // Shift the value to the correct place (according to place in inst)
            assert(endBitInInst >= 0 && "Negative shift amount!");
            if (endBitInInst != 0)
              o << "      op" << OpOrder[Vals[i].getName()]
              << " <<= " << endBitInInst << ";\n";

            // Just OR in the result
            o << "      Value |= op" << OpOrder[Vals[i].getName()] << ";\n";
          }

          // otherwise, will be taken care of in the loop below using this
          // value:
          OpContinuous[Vals[i].getName()] = continuous;
        }
      }
    }

    emitInstrOpBits(o, Vals, OpOrder, OpContinuous);

    o << "      break;\n"
      << "    }\n";
  }

  // Default case: unhandled opcode
  o << "  default:\n"
    << "    std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
    << "    abort();\n"
    << "  }\n"
    << "  return Value;\n"
    << "}\n\n";

  o << "} // End llvm namespace \n";
}
<commit_msg>The code emitter generator only supports targets with 32-bit instruction words.  There is no way for one of these targets to have a > 32-bit immediate!<commit_after>//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//

#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

void CodeEmitterGen::emitInstrOpBits(std::ostream &o,
                                     const std::vector<RecordVal> &Vals,
                                     std::map<std::string, unsigned> &OpOrder,
                                     std::map<std::string, bool> &OpContinuous)
{
  for (unsigned f = 0, e = Vals.size(); f != e; ++f) {
    if (Vals[f].getPrefix()) {
      BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();

      // Scan through the field looking for bit initializers of the current
      // variable...
      for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) {
        Init *I = FieldInitializer->getBit(i);
        if (BitInit *BI = dynamic_cast<BitInit*>(I)) {
          DEBUG(o << "      // bit init: f: " << f << ", i: " << i << "\n");
        } else if (UnsetInit *UI = dynamic_cast<UnsetInit*>(I)) {
          DEBUG(o << "      // unset init: f: " << f << ", i: " << i << "\n");
        } else if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(I)) {
          TypedInit *TI = VBI->getVariable();
          if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
            // If the bits of the field are laid out consecutively in the
            // instruction, then instead of separately ORing in bits, just
            // mask and shift the entire field for efficiency.
            if (OpContinuous[VI->getName()]) {
              // already taken care of in the loop above, thus there is no
              // need to individually OR in the bits

              // for debugging, output the regular version anyway, commented
              DEBUG(o << "      // Value |= getValueBit(op"
                      << OpOrder[VI->getName()] << ", " << VBI->getBitNum()
                      << ")" << " << " << i << ";\n");
            } else {
              o << "      Value |= getValueBit(op" << OpOrder[VI->getName()]
                << ", " << VBI->getBitNum()
                << ")" << " << " << i << ";\n";
            }
          } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
            // FIXME: implement this!
            std::cerr << "Error: FieldInit not implemented!\n";
            abort();
          } else {
            std::cerr << "Error: unimplemented case in "
                      << "CodeEmitterGen::emitInstrOpBits()\n";
            abort();
          }
        }
      }
    }
  }
}

void CodeEmitterGen::run(std::ostream &o) {
  CodeGenTarget Target;
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  EmitSourceFileHeader("Machine Code Emitter", o);
  o << "namespace llvm {\n\n";
  std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";

  // Emit function declaration
  o << "unsigned " << Target.getName() << "CodeEmitter::"
    << "getBinaryCodeForInstr(MachineInstr &MI) {\n"
    << "  unsigned Value = 0;\n"
    << "  DEBUG(std::cerr << MI);\n"
    << "  switch (MI.getOpcode()) {\n";

  // Emit a case statement for each opcode
  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
       I != E; ++I) {
    Record *R = *I;
    o << "    case " << Namespace << R->getName() << ": {\n"
      << "      DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n";

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    // For little-endian instruction bit encodings, reverse the bit order
    if (Target.isLittleEndianEncoding()) {
      unsigned numBits = BI->getNumBits();
      BitsInit *NewBI = new BitsInit(numBits);
      for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
        unsigned bitSwapIdx = numBits - bit - 1;
        Init *OrigBit = BI->getBit(bit);
        Init *BitSwap = BI->getBit(bitSwapIdx);
        NewBI->setBit(bit, BitSwap);
        NewBI->setBit(bitSwapIdx, OrigBit);
      }
      if (numBits % 2) {
        unsigned middle = (numBits + 1) / 2;
        NewBI->setBit(middle, BI->getBit(middle));
      }
      BI = NewBI;
    }

    unsigned Value = 0;
    const std::vector<RecordVal> &Vals = R->getValues();

    DEBUG(o << "      // prefilling: ");
    // Start by filling in fixed values...
    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
      if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
        Value |= B->getValue() << (e-i-1);
        DEBUG(o << B->getValue());
      } else {
        DEBUG(o << "0");
      }
    }
    DEBUG(o << "\n");

    DEBUG(o << "      // " << *R->getValue("Inst") << "\n");
    o << "      Value = " << Value << "U;\n\n";

    // Loop over all of the fields in the instruction, determining which are the
    // operands to the instruction.
    unsigned op = 0;
    std::map<std::string, unsigned> OpOrder;
    std::map<std::string, bool> OpContinuous;
    for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
      if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
        // Is the operand continuous? If so, we can just mask and OR it in
        // instead of doing it bit-by-bit, saving a lot in runtime cost.
        BitsInit *InstInit = BI;
        int beginBitInVar = -1, endBitInVar = -1;
        int beginBitInInst = -1, endBitInInst = -1;
        bool continuous = true;

        for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) {
          if (VarBitInit *VBI =
              dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) {
            TypedInit *TI = VBI->getVariable();
            if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
              // only process the current variable
              if (VI->getName() != Vals[i].getName())
                continue;

              if (beginBitInVar == -1)
                beginBitInVar = VBI->getBitNum();

              if (endBitInVar == -1)
                endBitInVar = VBI->getBitNum();
              else {
                if (endBitInVar == (int)VBI->getBitNum() + 1)
                  endBitInVar = VBI->getBitNum();
                else {
                  continuous = false;
                  break;
                }
              }

              if (beginBitInInst == -1)
                beginBitInInst = bit;
              if (endBitInInst == -1)
                endBitInInst = bit;
              else {
                if (endBitInInst == bit + 1)
                  endBitInInst = bit;
                else {
                  continuous = false;
                  break;
                }
              }

              // maintain same distance between bits in field and bits in
              // instruction. if the relative distances stay the same
              // throughout,
              if (beginBitInVar - (int)VBI->getBitNum() !=
                  beginBitInInst - bit) {
                continuous = false;
                break;
              }
            }
          }
        }

        // If we have found no bit in "Inst" which comes from this field, then
        // this is not an operand!!
        if (beginBitInInst != -1) {
          o << "      // op" << op << ": " << Vals[i].getName() << "\n"
            << "      int op" << op
            <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n";
          //<< "   MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n";
          OpOrder[Vals[i].getName()] = op++;

          DEBUG(o << "      // Var: begin = " << beginBitInVar
                  << ", end = " << endBitInVar
                  << "; Inst: begin = " << beginBitInInst
                  << ", end = " << endBitInInst << "\n");

          if (continuous) {
            DEBUG(o << "      // continuous: op" << OpOrder[Vals[i].getName()]
                    << "\n");

            // Mask off the right bits
            // Low mask (ie. shift, if necessary)
            assert(endBitInVar >= 0 && "Negative shift amount in masking!");
            if (endBitInVar != 0) {
              o << "      op" << OpOrder[Vals[i].getName()]
                << " >>= " << endBitInVar << ";\n";
              beginBitInVar -= endBitInVar;
              endBitInVar = 0;
            }

            // High mask
            o << "      op" << OpOrder[Vals[i].getName()]
              << " &= (1<<" << beginBitInVar+1 << ") - 1;\n";

            // Shift the value to the correct place (according to place in inst)
            assert(endBitInInst >= 0 && "Negative shift amount!");
            if (endBitInInst != 0)
              o << "      op" << OpOrder[Vals[i].getName()]
              << " <<= " << endBitInInst << ";\n";

            // Just OR in the result
            o << "      Value |= op" << OpOrder[Vals[i].getName()] << ";\n";
          }

          // otherwise, will be taken care of in the loop below using this
          // value:
          OpContinuous[Vals[i].getName()] = continuous;
        }
      }
    }

    emitInstrOpBits(o, Vals, OpOrder, OpContinuous);

    o << "      break;\n"
      << "    }\n";
  }

  // Default case: unhandled opcode
  o << "  default:\n"
    << "    std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
    << "    abort();\n"
    << "  }\n"
    << "  return Value;\n"
    << "}\n\n";

  o << "} // End llvm namespace \n";
}
<|endoftext|>