summaryrefslogtreecommitdiff
path: root/lib/VMCore/TypeSymbolTable.cpp
blob: d68a44bd6711c88df870a95e1e5c4ed77f2a75e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//===-- TypeSymbolTable.cpp - Implement the TypeSymbolTable class ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the TypeSymbolTable class for the VMCore library.
//
//===----------------------------------------------------------------------===//

#include "llvm/TypeSymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;

#define DEBUG_SYMBOL_TABLE 0
#define DEBUG_ABSTYPE 0

TypeSymbolTable::~TypeSymbolTable() {
  // Drop all abstract type references in the type plane...
  for (iterator TI = tmap.begin(), TE = tmap.end(); TI != TE; ++TI) {
    if (TI->second->isAbstract())   // If abstract, drop the reference...
      cast<DerivedType>(TI->second)->removeAbstractTypeUser(this);
  }
}

std::string TypeSymbolTable::getUniqueName(StringRef BaseName) const {
  std::string TryName = BaseName;
  
  const_iterator End = tmap.end();

  // See if the name exists
  while (tmap.find(TryName) != End)            // Loop until we find a free
    TryName = BaseName.str() + utostr(++LastUnique); // name in the symbol table
  return TryName;
}

// lookup a type by name - returns null on failure
Type* TypeSymbolTable::lookup(StringRef Name) const {
  const_iterator TI = tmap.find(Name);
  Type* result = 0;
  if (TI != tmap.end())
    result = const_cast<Type*>(TI->second);
  return result;
}

// remove - Remove a type from the symbol table...
Type* TypeSymbolTable::remove(iterator Entry) {
  assert(Entry != tmap.end() && "Invalid entry to remove!");
  const Type* Result = Entry->second;

#if DEBUG_SYMBOL_TABLE
  dump();
  dbgs() << " Removing Value: " << Result->getDescription() << "\n";
#endif

  tmap.erase(Entry);
  
  // If we are removing an abstract type, remove the symbol table from it's use
  // list...
  if (Result->isAbstract()) {
#if DEBUG_ABSTYPE
    dbgs() << "Removing abstract type from symtab"
           << Result->getDescription()
           << "\n";
#endif
    cast<DerivedType>(Result)->removeAbstractTypeUser(this);
  }

  return const_cast<Type*>(Result);
}


// insert - Insert a type into the symbol table with the specified name...
void TypeSymbolTable::insert(StringRef Name, const Type* T) {
  assert(T && "Can't insert null type into symbol table!");

  if (tmap.insert(std::make_pair(Name, T)).second) {
    // Type inserted fine with no conflict.
    
#if DEBUG_SYMBOL_TABLE
    dump();
    dbgs() << " Inserted type: " << Name << ": " << T->getDescription() << "\n";
#endif
  } else {
    // If there is a name conflict...
    
    // Check to see if there is a naming conflict.  If so, rename this type!
    std::string UniqueName = Name;
    if (lookup(Name))
      UniqueName = getUniqueName(Name);
    
#if DEBUG_SYMBOL_TABLE
    dump();
    dbgs() << " Inserting type: " << UniqueName << ": "
           << T->getDescription() << "\n";
#endif

    // Insert the tmap entry
    tmap.insert(make_pair(UniqueName, T));
  }
  
  // If we are adding an abstract type, add the symbol table to it's use list.
  if (T->isAbstract()) {
    cast<DerivedType>(T)->addAbstractTypeUser(this);
#if DEBUG_ABSTYPE
    dbgs() << "Added abstract type to ST: " << T->getDescription() << "\n";
#endif
  }
}

// This function is called when one of the types in the type plane are refined
void TypeSymbolTable::refineAbstractType(const DerivedType *OldType,
                                         const Type *NewType) {
  // Loop over all of the types in the symbol table, replacing any references
  // to OldType with references to NewType.  Note that there may be multiple
  // occurrences, and although we only need to remove one at a time, it's
  // faster to remove them all in one pass.
  //
  for (iterator I = begin(), E = end(); I != E; ++I) {
    // FIXME when Types aren't const.
    if (I->second == const_cast<DerivedType *>(OldType)) {
#if DEBUG_ABSTYPE
      dbgs() << "Removing type " << OldType->getDescription() << "\n";
#endif
      OldType->removeAbstractTypeUser(this);

      // TODO FIXME when types aren't const
      I->second = const_cast<Type *>(NewType);
      if (NewType->isAbstract()) {
#if DEBUG_ABSTYPE
        dbgs() << "Added type " << NewType->getDescription() << "\n";
#endif
        cast<DerivedType>(NewType)->addAbstractTypeUser(this);
      }
    }
  }
}


// Handle situation where type becomes Concreate from Abstract
void TypeSymbolTable::typeBecameConcrete(const DerivedType *AbsTy) {
  // Loop over all of the types in the symbol table, dropping any abstract
  // type user entries for AbsTy which occur because there are names for the
  // type.
  for (iterator TI = begin(), TE = end(); TI != TE; ++TI)
    if (TI->second == const_cast<Type*>(static_cast<const Type*>(AbsTy)))
      AbsTy->removeAbstractTypeUser(this);
}

static void DumpTypes(const std::pair<const std::string, const Type*>& T ) {
  dbgs() << "  '" << T.first << "' = ";
  T.second->dump();
  dbgs() << "\n";
}

void TypeSymbolTable::dump() const {
  dbgs() << "TypeSymbolPlane: ";
  for_each(tmap.begin(), tmap.end(), DumpTypes);
}