Introduce a new technique for merging BasicBlock with Instruction sentinel by superpo...
authorGabor Greif <ggreif@gmail.com>
Fri, 27 Feb 2009 08:41:37 +0000 (08:41 +0000)
committerGabor Greif <ggreif@gmail.com>
Fri, 27 Feb 2009 08:41:37 +0000 (08:41 +0000)
This looks dangerous, but isn't because the sentinel is accessed in special way only,
namely the Next and Prev fields of it, and these are guaranteed to exist.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@65626 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/ilist_node.h
include/llvm/BasicBlock.h
lib/VMCore/BasicBlock.cpp

index d68f3f23618d895d8789fe35805292b2a0c8b437..86d5a500f89eb7697573d2857c8e843ec5fd86ba 100644 (file)
@@ -20,6 +20,9 @@ namespace llvm {
 template<typename NodeTy>
 struct ilist_nextprev_traits;
 
+template<typename NodeTy>
+struct ilist_traits;
+
 /// ilist_node - Base class that provides next/prev services for nodes
 /// that use ilist_nextprev_traits or ilist_default_traits.
 ///
@@ -36,6 +39,7 @@ private:
   void setNext(NodeTy *N) { Next = N; }
 protected:
   ilist_node() : Prev(0), Next(0) {}
+  friend struct ilist_traits<NodeTy>;
 };
 
 } // End llvm namespace
index 780aca5ef6df3176d508aafe5f74142aff57d17a..29caa0ab192e213c81fa2d65344f23e46704de4f 100644 (file)
@@ -26,11 +26,15 @@ class TerminatorInst;
 template<> struct ilist_traits<Instruction>
   : public SymbolTableListTraits<Instruction, BasicBlock> {
   // createSentinel is used to create a node that marks the end of the list...
-  static Instruction *createSentinel();
-  static void destroySentinel(Instruction *I) { delete I; }
+  Instruction *createSentinel() const {
+    return const_cast<Instruction*>(static_cast<const Instruction*>(&Sentinel));
+  }
+  static void destroySentinel(Instruction *I) { }
   static iplist<Instruction> &getList(BasicBlock *BB);
   static ValueSymbolTable *getSymTab(BasicBlock *ItemParent);
   static int getListOffset();
+private:
+  ilist_node<Instruction> Sentinel;
 };
 
 /// This represents a single basic block in LLVM. A basic block is simply a
@@ -49,9 +53,10 @@ template<> struct ilist_traits<Instruction>
 /// @brief LLVM Basic Block Representation
 class BasicBlock : public Value, // Basic blocks are data objects also
                    public ilist_node<BasicBlock> {
+
 public:
   typedef iplist<Instruction> InstListType;
-private :
+private:
   InstListType InstList;
   Function *Parent;
 
index a76f659233d4270f4ed29e1db56a292f1fa8c56c..66ee99d1745c2df4b504a2957131579f3c698a2e 100644 (file)
@@ -31,40 +31,6 @@ ilist_traits<Instruction>::getSymTab(BasicBlock *BB) {
   return 0;
 }
 
-
-namespace {
-  /// DummyInst - An instance of this class is used to mark the end of the
-  /// instruction list.  This is not a real instruction.
-  struct VISIBILITY_HIDDEN DummyInst : public Instruction {
-    // allocate space for exactly zero operands
-    void *operator new(size_t s) {
-      return User::operator new(s, 0);
-    }
-    DummyInst() : Instruction(Type::VoidTy, OtherOpsEnd, 0, 0) {
-      // This should not be garbage monitored.
-      LeakDetector::removeGarbageObject(this);
-    }
-
-    Instruction *clone() const {
-      assert(0 && "Cannot clone EOL");abort();
-      return 0;
-    }
-    const char *getOpcodeName() const { return "*end-of-list-inst*"; }
-
-    // Methods for support type inquiry through isa, cast, and dyn_cast...
-    static inline bool classof(const DummyInst *) { return true; }
-    static inline bool classof(const Instruction *I) {
-      return I->getOpcode() == OtherOpsEnd;
-    }
-    static inline bool classof(const Value *V) {
-      return isa<Instruction>(V) && classof(cast<Instruction>(V));
-    }
-  };
-}
-
-Instruction *ilist_traits<Instruction>::createSentinel() {
-  return new DummyInst();
-}
 iplist<Instruction> &ilist_traits<Instruction>::getList(BasicBlock *BB) {
   return BB->getInstList();
 }