diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 60589ba7f10..c60e5eeb0b9 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -46,16 +46,24 @@ public: /// @brief A mapping of Values to slot numbers typedef std::map ValueMap; + typedef std::map TypeMap; /// @brief A plane with next slot number and ValueMap - struct Plane { + struct ValuePlane { unsigned next_slot; ///< The next slot number to use ValueMap map; ///< The map of Value* -> unsigned - Plane() { next_slot = 0; } ///< Make sure we start at 0 + ValuePlane() { next_slot = 0; } ///< Make sure we start at 0 + }; + + struct TypePlane { + unsigned next_slot; + TypeMap map; + TypePlane() { next_slot = 0; } + void clear() { map.clear(); next_slot = 0; } }; /// @brief The map of planes by Type - typedef std::map TypedPlanes; + typedef std::map TypedPlanes; /// @} /// @name Constructors @@ -75,9 +83,11 @@ public: /// plane. Its an error to ask for something not in the SlotMachine. /// Its an error to ask for a Type* int getSlot(const Value *V); + int getSlot(const Type*Ty); /// Determine if a Value has a slot or not bool hasSlot(const Value* V); + bool hasSlot(const Type* Ty); /// @} /// @name Mutators @@ -103,11 +113,13 @@ private: /// been inserted already, they get inserted, otherwise they are ignored. /// Either way, the slot number for the Value* is returned. unsigned createSlot(const Value *V); + unsigned createSlot(const Type* Ty); /// Insert a value into the value table. Return the slot number /// that it now occupies. BadThings(TM) will happen if you insert a /// Value that's already been inserted. unsigned insertValue( const Value *V ); + unsigned insertValue( const Type* Ty); /// Add all of the module level global variables (and their initializers) /// and function declarations, but not the contents of those functions. @@ -132,9 +144,11 @@ public: /// @brief The TypePlanes map for the module level data TypedPlanes mMap; + TypePlane mTypes; /// @brief The TypePlanes map for the function level data TypedPlanes fMap; + TypePlane fTypes; /// @} @@ -152,6 +166,11 @@ static void WriteAsOperandInternal(std::ostream &Out, const Value *V, std::map &TypeTable, SlotMachine *Machine); +static void WriteAsOperandInternal(std::ostream &Out, const Type *T, + bool PrintName, + std::map &TypeTable, + SlotMachine *Machine); + static const Module *getModuleFromVal(const Value *V) { if (const Argument *MA = dyn_cast(V)) return MA->getParent() ? MA->getParent()->getParent() : 0; @@ -166,7 +185,6 @@ static const Module *getModuleFromVal(const Value *V) { } static SlotMachine *createSlotMachine(const Value *V) { - assert(!isa(V) && "Can't create an SC for a type!"); if (const Argument *FA = dyn_cast(V)) { return new SlotMachine(FA->getParent()); } else if (const Instruction *I = dyn_cast(V)) { @@ -519,11 +537,6 @@ static void WriteAsOperandInternal(std::ostream &Out, const Value *V, if (Machine) { Slot = Machine->getSlot(V); } else { - if (const Type *Ty = dyn_cast(V)) { - Out << Ty->getDescription(); - return; - } - Machine = createSlotMachine(V); if (Machine == 0) Slot = Machine->getSlot(V); @@ -539,7 +552,6 @@ static void WriteAsOperandInternal(std::ostream &Out, const Value *V, } } - /// WriteAsOperand - Write the name of the specified value out to the specified /// ostream. This can be useful when you just want to print int %reg126, not /// the whole instruction that generated it. @@ -556,13 +568,52 @@ std::ostream &llvm::WriteAsOperand(std::ostream &Out, const Value *V, if (PrintType) printTypeInt(Out, V->getType(), TypeNames); - if (const Type *Ty = dyn_cast (V)) - printTypeInt(Out, Ty, TypeNames); - WriteAsOperandInternal(Out, V, PrintName, TypeNames, 0); return Out; } +/// WriteAsOperandInternal - Write the name of the specified value out to +/// the specified ostream. This can be useful when you just want to print +/// int %reg126, not the whole instruction that generated it. +/// +static void WriteAsOperandInternal(std::ostream &Out, const Type *T, + bool PrintName, + std::map &TypeTable, + SlotMachine *Machine) { + Out << ' '; + int Slot; + if (Machine) { + Slot = Machine->getSlot(T); + if (Slot != -1) + Out << '%' << Slot; + else + Out << ""; + } else { + Out << T->getDescription(); + } +} + +/// WriteAsOperand - Write the name of the specified value out to the specified +/// ostream. This can be useful when you just want to print int %reg126, not +/// the whole instruction that generated it. +/// +std::ostream &llvm::WriteAsOperand(std::ostream &Out, const Type *Ty, + bool PrintType, bool PrintName, + const Module *Context) { + std::map TypeNames; + assert(Context != 0 && "Can't write types as operand without module context"); + + fillTypeNameTable(Context, TypeNames); + + // if (PrintType) + // printTypeInt(Out, V->getType(), TypeNames); + + printTypeInt(Out, Ty, TypeNames); + + WriteAsOperandInternal(Out, Ty, PrintName, TypeNames, 0); + return Out; +} + namespace llvm { class AssemblyWriter { @@ -1171,20 +1222,19 @@ CachedWriter &CachedWriter::operator<<(const Value *V) { AW->write(F); else if (const GlobalVariable *GV = dyn_cast(V)) AW->write(GV); - else if (const Type *Ty = dyn_cast(V)) - AW->write(Ty); else AW->writeOperand(V, true, true); return *this; } -CachedWriter& CachedWriter::operator<<(const Type *X) { +CachedWriter& CachedWriter::operator<<(const Type *Ty) { if (SymbolicTypes) { const Module *M = AW->getModule(); - if (M) WriteTypeSymbolic(Out, X, M); - return *this; - } else - return *this << (const Value*)X; + if (M) WriteTypeSymbolic(Out, Ty, M); + } else { + AW->write(Ty); + } + return *this; } //===----------------------------------------------------------------------===// @@ -1203,7 +1253,9 @@ SlotMachine::SlotMachine(const Module *M) : TheModule(M) ///< Saved for lazy initialization. , TheFunction(0) , mMap() + , mTypes() , fMap() + , fTypes() { } @@ -1213,7 +1265,9 @@ SlotMachine::SlotMachine(const Function *F ) : TheModule( F ? F->getParent() : 0 ) ///< Saved for lazy initialization , TheFunction(F) ///< Saved for lazy initialization , mMap() + , mTypes() , fMap() + , fTypes() { } @@ -1276,6 +1330,7 @@ void SlotMachine::processFunction() { void SlotMachine::purgeFunction() { SC_DEBUG("begin purgeFunction!\n"); fMap.clear(); // Simply discard the function level map + fTypes.clear(); TheFunction = 0; SC_DEBUG("end purgeFunction!\n"); } @@ -1285,7 +1340,6 @@ void SlotMachine::purgeFunction() { /// 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(V) && "Can't get slot for a type" ); assert(!isa(V) || isa(V) && "Can't insert a non-GlobalValue Constant into SlotMachine"); @@ -1346,12 +1400,51 @@ int SlotMachine::getSlot(const Value *V) { 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(V) && "Can't insert a Type into SlotMachine"); assert(!isa(V) || isa(V) && "Can't insert a non-GlobalValue Constant into SlotMachine"); @@ -1428,12 +1521,49 @@ unsigned SlotMachine::createSlot(const Value *V) { 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(V) && "Can't insert a Type into SlotMachine!"); assert(!isa(V) || isa(V) && "Can't insert a non-GlobalValue Constant into SlotMachine"); @@ -1450,12 +1580,12 @@ unsigned SlotMachine::insertValue(const Value *V ) { if ( TheFunction ) { TypedPlanes::iterator I = fMap.find( VTy ); if ( I == fMap.end() ) - I = fMap.insert(std::make_pair(VTy,Plane())).first; + 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,Plane())).first; + I = mMap.insert(std::make_pair(VTy,ValuePlane())).first; DestSlot = I->second.map[V] = I->second.next_slot++; } @@ -1468,4 +1598,20 @@ unsigned SlotMachine::insertValue(const Value *V ) { 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