+ /// After calling incorporateFunction, use this method to remove the
+ /// most recently incorporated function from the SlotMachine. This
+ /// will reset the state of the machine back to just the module contents.
+ void purgeFunction();
+
+/// @}
+/// @name Implementation Details
+/// @{
+private:
+ /// This function does the actual initialization.
+ inline void initialize();
+
+ /// Values can be crammed into here at will. If they haven't
+ /// 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.
+ void processModule();
+
+ /// Add all of the functions arguments, basic blocks, and instructions
+ void processFunction();
+
+ SlotMachine(const SlotMachine &); // DO NOT IMPLEMENT
+ void operator=(const SlotMachine &); // DO NOT IMPLEMENT
+
+/// @}
+/// @name Data
+/// @{
+public:
+
+ /// @brief The module for which we are holding slot numbers
+ const Module* TheModule;
+
+ /// @brief The function for which we are holding slot numbers
+ const Function* TheFunction;
+ bool FunctionProcessed;
+
+ /// @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;
+
+/// @}
+
+};
+
+} // end namespace llvm
+
+static RegisterPass<PrintModulePass>
+X("printm", "Print module to stderr",PassInfo::Analysis|PassInfo::Optimization);
+static RegisterPass<PrintFunctionPass>
+Y("print","Print function to stderr",PassInfo::Analysis|PassInfo::Optimization);
+
+static void WriteAsOperandInternal(std::ostream &Out, const Value *V,
+ bool PrintName,
+ std::map<const Type *, std::string> &TypeTable,
+ SlotMachine *Machine);
+
+static void WriteAsOperandInternal(std::ostream &Out, const Type *T,
+ bool PrintName,
+ std::map<const Type *, std::string> &TypeTable,
+ SlotMachine *Machine);
+
+static const Module *getModuleFromVal(const Value *V) {
+ if (const Argument *MA = dyn_cast<Argument>(V))
+ return MA->getParent() ? MA->getParent()->getParent() : 0;
+ else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
+ return BB->getParent() ? BB->getParent()->getParent() : 0;
+ else if (const Instruction *I = dyn_cast<Instruction>(V)) {
+ const Function *M = I->getParent() ? I->getParent()->getParent() : 0;
+ return M ? M->getParent() : 0;
+ } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
+ return GV->getParent();
+ return 0;
+}
+
+static SlotMachine *createSlotMachine(const Value *V) {
+ if (const Argument *FA = dyn_cast<Argument>(V)) {
+ return new SlotMachine(FA->getParent());
+ } else if (const Instruction *I = dyn_cast<Instruction>(V)) {
+ return new SlotMachine(I->getParent()->getParent());
+ } else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V)) {
+ return new SlotMachine(BB->getParent());
+ } else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)){
+ return new SlotMachine(GV->getParent());
+ } else if (const Function *Func = dyn_cast<Function>(V)) {
+ return new SlotMachine(Func);
+ }
+ return 0;
+}
+
+// getLLVMName - Turn the specified string into an 'LLVM name', which is either
+// prefixed with % (if the string only contains simple characters) or is
+// surrounded with ""'s (if it has special chars in it).
+static std::string getLLVMName(const std::string &Name,
+ bool prefixName = true) {
+ assert(!Name.empty() && "Cannot get empty name!");
+
+ // First character cannot start with a number...
+ if (Name[0] >= '0' && Name[0] <= '9')
+ return "\"" + Name + "\"";
+
+ // Scan to see if we have any characters that are not on the "white list"
+ for (unsigned i = 0, e = Name.size(); i != e; ++i) {
+ char C = Name[i];
+ assert(C != '"' && "Illegal character in LLVM value name!");
+ if ((C < 'a' || C > 'z') && (C < 'A' || C > 'Z') && (C < '0' || C > '9') &&
+ C != '-' && C != '.' && C != '_')
+ return "\"" + Name + "\"";
+ }
+
+ // If we get here, then the identifier is legal to use as a "VarID".
+ if (prefixName)
+ return "%"+Name;
+ else
+ return Name;
+}
+
+
+/// fillTypeNameTable - If the module has a symbol table, take all global types
+/// and stuff their names into the TypeNames map.
+///
+static void fillTypeNameTable(const Module *M,
+ std::map<const Type *, std::string> &TypeNames) {
+ if (!M) return;
+ const SymbolTable &ST = M->getSymbolTable();
+ SymbolTable::type_const_iterator TI = ST.type_begin();
+ for (; TI != ST.type_end(); ++TI ) {
+ // As a heuristic, don't insert pointer to primitive types, because
+ // they are used too often to have a single useful name.
+ //
+ const Type *Ty = cast<Type>(TI->second);
+ if (!isa<PointerType>(Ty) ||
+ !cast<PointerType>(Ty)->getElementType()->isPrimitiveType() ||
+ isa<OpaqueType>(cast<PointerType>(Ty)->getElementType()))
+ TypeNames.insert(std::make_pair(Ty, getLLVMName(TI->first)));
+ }
+}
+
+
+
+static void calcTypeName(const Type *Ty,
+ std::vector<const Type *> &TypeStack,
+ std::map<const Type *, std::string> &TypeNames,
+ std::string & Result){
+ if (Ty->isPrimitiveType() && !isa<OpaqueType>(Ty)) {
+ Result += Ty->getDescription(); // Base case
+ return;
+ }
+
+ // Check to see if the type is named.
+ std::map<const Type *, std::string>::iterator I = TypeNames.find(Ty);
+ if (I != TypeNames.end()) {
+ Result += I->second;
+ return;
+ }
+
+ if (isa<OpaqueType>(Ty)) {
+ Result += "opaque";
+ return;
+ }
+
+ // Check to see if the Type is already on the stack...
+ unsigned Slot = 0, CurSize = TypeStack.size();
+ while (Slot < CurSize && TypeStack[Slot] != Ty) ++Slot; // Scan for type
+
+ // This is another base case for the recursion. In this case, we know
+ // that we have looped back to a type that we have previously visited.
+ // Generate the appropriate upreference to handle this.
+ if (Slot < CurSize) {
+ Result += "\\" + utostr(CurSize-Slot); // Here's the upreference
+ return;
+ }
+
+ TypeStack.push_back(Ty); // Recursive case: Add us to the stack..
+
+ switch (Ty->getTypeID()) {
+ case Type::FunctionTyID: {
+ const FunctionType *FTy = cast<FunctionType>(Ty);
+ calcTypeName(FTy->getReturnType(), TypeStack, TypeNames, Result);
+ Result += " (";
+ for (FunctionType::param_iterator I = FTy->param_begin(),
+ E = FTy->param_end(); I != E; ++I) {
+ if (I != FTy->param_begin())
+ Result += ", ";
+ calcTypeName(*I, TypeStack, TypeNames, Result);
+ }
+ if (FTy->isVarArg()) {
+ if (FTy->getNumParams()) Result += ", ";
+ Result += "...";
+ }
+ Result += ")";
+ break;
+ }
+ case Type::StructTyID: {
+ const StructType *STy = cast<StructType>(Ty);
+ Result += "{ ";
+ for (StructType::element_iterator I = STy->element_begin(),
+ E = STy->element_end(); I != E; ++I) {
+ if (I != STy->element_begin())
+ Result += ", ";
+ calcTypeName(*I, TypeStack, TypeNames, Result);
+ }
+ Result += " }";
+ break;
+ }
+ case Type::PointerTyID:
+ calcTypeName(cast<PointerType>(Ty)->getElementType(),
+ TypeStack, TypeNames, Result);
+ Result += "*";
+ break;
+ case Type::ArrayTyID: {
+ const ArrayType *ATy = cast<ArrayType>(Ty);
+ Result += "[" + utostr(ATy->getNumElements()) + " x ";
+ calcTypeName(ATy->getElementType(), TypeStack, TypeNames, Result);
+ Result += "]";
+ break;
+ }
+ case Type::PackedTyID: {
+ const PackedType *PTy = cast<PackedType>(Ty);
+ Result += "<" + utostr(PTy->getNumElements()) + " x ";
+ calcTypeName(PTy->getElementType(), TypeStack, TypeNames, Result);
+ Result += ">";
+ break;
+ }
+ case Type::OpaqueTyID:
+ Result += "opaque";
+ break;
+ default:
+ Result += "<unrecognized-type>";
+ }
+
+ TypeStack.pop_back(); // Remove self from stack...
+ return;
+}
+
+
+/// printTypeInt - The internal guts of printing out a type that has a
+/// potentially named portion.
+///
+static std::ostream &printTypeInt(std::ostream &Out, const Type *Ty,
+ std::map<const Type *, std::string> &TypeNames) {
+ // Primitive types always print out their description, regardless of whether
+ // they have been named or not.
+ //
+ if (Ty->isPrimitiveType() && !isa<OpaqueType>(Ty))
+ return Out << Ty->getDescription();
+
+ // Check to see if the type is named.
+ std::map<const Type *, std::string>::iterator I = TypeNames.find(Ty);
+ if (I != TypeNames.end()) return Out << I->second;
+
+ // Otherwise we have a type that has not been named but is a derived type.
+ // Carefully recurse the type hierarchy to print out any contained symbolic
+ // names.
+ //
+ std::vector<const Type *> TypeStack;
+ std::string TypeName;
+ calcTypeName(Ty, TypeStack, TypeNames, TypeName);
+ TypeNames.insert(std::make_pair(Ty, TypeName));//Cache type name for later use
+ return (Out << TypeName);
+}
+
+
+/// WriteTypeSymbolic - This attempts to write the specified type as a symbolic
+/// type, iff there is an entry in the modules symbol table for the specified
+/// type or one of it's component types. This is slower than a simple x << Type
+///
+std::ostream &llvm::WriteTypeSymbolic(std::ostream &Out, const Type *Ty,
+ const Module *M) {
+ Out << ' ';
+
+ // If they want us to print out a type, attempt to make it symbolic if there
+ // is a symbol table in the module...
+ if (M) {
+ std::map<const Type *, std::string> TypeNames;
+ fillTypeNameTable(M, TypeNames);
+
+ return printTypeInt(Out, Ty, TypeNames);
+ } else {
+ return Out << Ty->getDescription();
+ }
+}