+
+//===----------------------------------------------------------------------===//
+//===-- SlotMachine Implementation
+//===----------------------------------------------------------------------===//
+
+#if 0
+#define SC_DEBUG(X) std::cerr << X
+#else
+#define SC_DEBUG(X)
+#endif
+
+// Module level constructor. Causes the contents of the Module (sans functions)
+// to be added to the slot table.
+SlotMachine::SlotMachine(const Module *M)
+ : TheModule(M) ///< Saved for lazy initialization.
+ , TheFunction(0)
+ , FunctionProcessed(false)
+ , mMap()
+ , mTypes()
+ , fMap()
+ , fTypes()
+{
+}
+
+// Function level constructor. Causes the contents of the Module and the one
+// function provided to be added to the slot table.
+SlotMachine::SlotMachine(const Function *F )
+ : TheModule( F ? F->getParent() : 0 ) ///< Saved for lazy initialization
+ , TheFunction(F) ///< Saved for lazy initialization
+ , FunctionProcessed(false)
+ , mMap()
+ , mTypes()
+ , fMap()
+ , fTypes()
+{
+}
+
+inline void SlotMachine::initialize(void) {
+ if ( TheModule) {
+ processModule();
+ TheModule = 0; ///< Prevent re-processing next time we're called.
+ }
+ if ( TheFunction && ! FunctionProcessed) {
+ processFunction();
+ }
+}
+
+// Iterate through all the global variables, functions, and global
+// variable initializers and create slots for them.
+void SlotMachine::processModule() {
+ SC_DEBUG("begin processModule!\n");
+
+ // Add all of the global variables to the value table...
+ for (Module::const_giterator I = TheModule->gbegin(), E = TheModule->gend();
+ I != E; ++I)
+ createSlot(I);
+
+ // Add all the functions to the table
+ for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
+ I != E; ++I)
+ createSlot(I);
+
+ SC_DEBUG("end processModule!\n");
+}
+
+
+// Process the arguments, basic blocks, and instructions of a function.
+void SlotMachine::processFunction() {
+ SC_DEBUG("begin processFunction!\n");
+
+ // Add all the function arguments
+ for(Function::const_aiterator AI = TheFunction->abegin(),
+ AE = TheFunction->aend(); AI != AE; ++AI)
+ createSlot(AI);
+
+ SC_DEBUG("Inserting Instructions:\n");
+
+ // Add all of the basic blocks and instructions
+ for (Function::const_iterator BB = TheFunction->begin(),
+ E = TheFunction->end(); BB != E; ++BB) {
+ createSlot(BB);
+ for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
+ createSlot(I);
+ }
+ }
+
+ FunctionProcessed = true;
+
+ SC_DEBUG("end processFunction!\n");
+}
+
+// Clean up after incorporating a function. This is the only way
+// to get out of the function incorporation state that affects the
+// getSlot/createSlot lock. Function incorporation state is indicated
+// by TheFunction != 0.
+void SlotMachine::purgeFunction() {
+ SC_DEBUG("begin purgeFunction!\n");
+ fMap.clear(); // Simply discard the function level map
+ fTypes.clear();
+ TheFunction = 0;
+ FunctionProcessed = false;
+ SC_DEBUG("end purgeFunction!\n");
+}
+
+/// Get the slot number for a value. This function will assert if you
+/// ask for a Value that hasn't previously been inserted with createSlot.
+/// Types are forbidden because Type does not inherit from Value (any more).
+int SlotMachine::getSlot(const Value *V) {
+ assert( V && "Can't get slot for null Value" );
+ assert(!isa<Constant>(V) || isa<GlobalValue>(V) &&
+ "Can't insert a non-GlobalValue Constant into SlotMachine");
+
+ // Check for uninitialized state and do lazy initialization
+ this->initialize();
+
+ // Get the type of the value
+ const Type* VTy = V->getType();
+
+ // Find the type plane in the module map
+ TypedPlanes::const_iterator MI = mMap.find(VTy);
+
+ if ( TheFunction ) {
+ // Lookup the type in the function map too
+ TypedPlanes::const_iterator FI = fMap.find(VTy);
+ // If there is a corresponding type plane in the function map
+ if ( FI != fMap.end() ) {
+ // Lookup the Value in the function map
+ ValueMap::const_iterator FVI = FI->second.map.find(V);
+ // If the value doesn't exist in the function map
+ if ( FVI == FI->second.map.end() ) {
+ // Look up the value in the module map.
+ if (MI == mMap.end()) return -1;
+ ValueMap::const_iterator MVI = MI->second.map.find(V);
+ // If we didn't find it, it wasn't inserted
+ if (MVI == MI->second.map.end()) return -1;
+ assert( MVI != MI->second.map.end() && "Value not found");
+ // We found it only at the module level
+ return MVI->second;
+
+ // else the value exists in the function map
+ } else {
+ // Return the slot number as the module's contribution to
+ // the type plane plus the index in the function's contribution
+ // to the type plane.
+ if (MI != mMap.end())
+ return MI->second.next_slot + FVI->second;
+ else
+ return FVI->second;
+ }
+ }
+ }
+
+ // N.B. Can get here only if either !TheFunction or the function doesn't
+ // have a corresponding type plane for the Value
+
+ // Make sure the type plane exists
+ if (MI == mMap.end()) return -1;
+ // Lookup the value in the module's map
+ ValueMap::const_iterator MVI = MI->second.map.find(V);
+ // Make sure we found it.
+ if (MVI == MI->second.map.end()) return -1;
+ // Return it.
+ return MVI->second;
+}
+
+/// Get the slot number for a value. This function will assert if you
+/// ask for a Value that hasn't previously been inserted with createSlot.
+/// Types are forbidden because Type does not inherit from Value (any more).
+int SlotMachine::getSlot(const Type *Ty) {
+ assert( Ty && "Can't get slot for null Type" );
+
+ // Check for uninitialized state and do lazy initialization
+ this->initialize();
+
+ if ( TheFunction ) {
+ // Lookup the Type in the function map
+ TypeMap::const_iterator FTI = fTypes.map.find(Ty);
+ // If the Type doesn't exist in the function map
+ if ( FTI == fTypes.map.end() ) {
+ TypeMap::const_iterator MTI = mTypes.map.find(Ty);
+ // If we didn't find it, it wasn't inserted
+ if (MTI == mTypes.map.end())
+ return -1;
+ // We found it only at the module level
+ return MTI->second;
+
+ // else the value exists in the function map
+ } else {
+ // Return the slot number as the module's contribution to
+ // the type plane plus the index in the function's contribution
+ // to the type plane.
+ return mTypes.next_slot + FTI->second;
+ }
+ }
+
+ // N.B. Can get here only if either !TheFunction
+
+ // Lookup the value in the module's map
+ TypeMap::const_iterator MTI = mTypes.map.find(Ty);
+ // Make sure we found it.
+ if (MTI == mTypes.map.end()) return -1;
+ // Return it.
+ return MTI->second;
+}
+
+// Create a new slot, or return the existing slot if it is already
+// inserted. Note that the logic here parallels getSlot but instead
+// of asserting when the Value* isn't found, it inserts the value.
+unsigned SlotMachine::createSlot(const Value *V) {
+ assert( V && "Can't insert a null Value to SlotMachine");
+ assert(!isa<Constant>(V) || isa<GlobalValue>(V) &&
+ "Can't insert a non-GlobalValue Constant into SlotMachine");
+
+ const Type* VTy = V->getType();
+
+ // Just ignore void typed things
+ if (VTy == Type::VoidTy) return 0; // FIXME: Wrong return value!
+
+ // Look up the type plane for the Value's type from the module map
+ TypedPlanes::const_iterator MI = mMap.find(VTy);
+
+ if ( TheFunction ) {
+ // Get the type plane for the Value's type from the function map
+ TypedPlanes::const_iterator FI = fMap.find(VTy);
+ // If there is a corresponding type plane in the function map
+ if ( FI != fMap.end() ) {
+ // Lookup the Value in the function map
+ ValueMap::const_iterator FVI = FI->second.map.find(V);
+ // If the value doesn't exist in the function map
+ if ( FVI == FI->second.map.end() ) {
+ // If there is no corresponding type plane in the module map
+ if ( MI == mMap.end() )
+ return insertValue(V);
+ // Look up the value in the module map
+ ValueMap::const_iterator MVI = MI->second.map.find(V);
+ // If we didn't find it, it wasn't inserted
+ if ( MVI == MI->second.map.end() )
+ return insertValue(V);
+ else
+ // We found it only at the module level
+ return MVI->second;
+
+ // else the value exists in the function map
+ } else {
+ if ( MI == mMap.end() )
+ return FVI->second;
+ else
+ // Return the slot number as the module's contribution to
+ // the type plane plus the index in the function's contribution
+ // to the type plane.
+ return MI->second.next_slot + FVI->second;
+ }
+
+ // else there is not a corresponding type plane in the function map
+ } else {
+ // If the type plane doesn't exists at the module level
+ if ( MI == mMap.end() ) {
+ return insertValue(V);
+ // else type plane exists at the module level, examine it
+ } else {
+ // Look up the value in the module's map
+ ValueMap::const_iterator MVI = MI->second.map.find(V);
+ // If we didn't find it there either
+ if ( MVI == MI->second.map.end() )
+ // Return the slot number as the module's contribution to
+ // the type plane plus the index of the function map insertion.
+ return MI->second.next_slot + insertValue(V);
+ else
+ return MVI->second;
+ }
+ }
+ }
+
+ // N.B. Can only get here if !TheFunction
+
+ // If the module map's type plane is not for the Value's type
+ if ( MI != mMap.end() ) {
+ // Lookup the value in the module's map
+ ValueMap::const_iterator MVI = MI->second.map.find(V);
+ if ( MVI != MI->second.map.end() )
+ return MVI->second;
+ }
+
+ return insertValue(V);
+}
+
+// Create a new slot, or return the existing slot if it is already
+// inserted. Note that the logic here parallels getSlot but instead
+// of asserting when the Value* isn't found, it inserts the value.
+unsigned SlotMachine::createSlot(const Type *Ty) {
+ assert( Ty && "Can't insert a null Type to SlotMachine");
+
+ if ( TheFunction ) {
+ // Lookup the Type in the function map
+ TypeMap::const_iterator FTI = fTypes.map.find(Ty);
+ // If the type doesn't exist in the function map
+ if ( FTI == fTypes.map.end() ) {
+ // Look up the type in the module map
+ TypeMap::const_iterator MTI = mTypes.map.find(Ty);
+ // If we didn't find it, it wasn't inserted
+ if ( MTI == mTypes.map.end() )
+ return insertValue(Ty);
+ else
+ // We found it only at the module level
+ return MTI->second;
+
+ // else the value exists in the function map
+ } else {
+ // Return the slot number as the module's contribution to
+ // the type plane plus the index in the function's contribution
+ // to the type plane.
+ return mTypes.next_slot + FTI->second;
+ }
+ }
+
+ // N.B. Can only get here if !TheFunction
+
+ // Lookup the type in the module's map
+ TypeMap::const_iterator MTI = mTypes.map.find(Ty);
+ if ( MTI != mTypes.map.end() )
+ return MTI->second;
+
+ return insertValue(Ty);
+}
+
+// Low level insert function. Minimal checking is done. This
+// function is just for the convenience of createSlot (above).
+unsigned SlotMachine::insertValue(const Value *V ) {
+ assert(V && "Can't insert a null Value into SlotMachine!");
+ assert(!isa<Constant>(V) || isa<GlobalValue>(V) &&
+ "Can't insert a non-GlobalValue Constant into SlotMachine");
+
+ // If this value does not contribute to a plane (is void)
+ // or if the value already has a name then ignore it.
+ if (V->getType() == Type::VoidTy || V->hasName() ) {
+ SC_DEBUG("ignored value " << *V << "\n");
+ return 0; // FIXME: Wrong return value
+ }
+
+ const Type *VTy = V->getType();
+ unsigned DestSlot = 0;
+
+ if ( TheFunction ) {
+ TypedPlanes::iterator I = fMap.find( VTy );
+ if ( I == fMap.end() )
+ I = fMap.insert(std::make_pair(VTy,ValuePlane())).first;
+ DestSlot = I->second.map[V] = I->second.next_slot++;
+ } else {
+ TypedPlanes::iterator I = mMap.find( VTy );
+ if ( I == mMap.end() )
+ I = mMap.insert(std::make_pair(VTy,ValuePlane())).first;
+ DestSlot = I->second.map[V] = I->second.next_slot++;
+ }
+
+ SC_DEBUG(" Inserting value [" << VTy << "] = " << V << " slot=" <<
+ DestSlot << " [");
+ // G = Global, C = Constant, T = Type, F = Function, o = other
+ SC_DEBUG((isa<GlobalVariable>(V) ? 'G' : (isa<Function>(V) ? 'F' :
+ (isa<Constant>(V) ? 'C' : 'o'))));
+ SC_DEBUG("]\n");
+ return DestSlot;
+}
+
+// Low level insert function. Minimal checking is done. This
+// function is just for the convenience of createSlot (above).
+unsigned SlotMachine::insertValue(const Type *Ty ) {
+ assert(Ty && "Can't insert a null Type into SlotMachine!");
+
+ unsigned DestSlot = 0;
+
+ if ( TheFunction ) {
+ DestSlot = fTypes.map[Ty] = fTypes.next_slot++;
+ } else {
+ DestSlot = fTypes.map[Ty] = fTypes.next_slot++;
+ }
+ SC_DEBUG(" Inserting type [" << DestSlot << "] = " << Ty << "\n");
+ return DestSlot;
+}
+
+// vim: sw=2