//===-- AsmWriter.cpp - Printing LLVM as an assembly file -----------------===//
//
// This library implements the functionality defined in llvm/Assembly/Writer.h
//
// Note that these routines must be extremely tolerant of various errors in the
// LLVM code, because of of the primary uses of it is for debugging
// transformations.
//
// TODO: print out the type name instead of the full type if a particular type
// is in the symbol table...
//
//===----------------------------------------------------------------------===//
#include "llvm/Assembly/CachedWriter.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/SlotCalculator.h"
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/BasicBlock.h"
#include "llvm/ConstantVals.h"
#include "llvm/iMemory.h"
#include "llvm/iTerminators.h"
#include "llvm/iPHINode.h"
#include "llvm/iOther.h"
#include "llvm/SymbolTable.h"
#include "llvm/Argument.h"
#include "Support/StringExtras.h"
#include "Support/STLExtras.h"
#include <algorithm>
#include <map>
using std::string;
using std::map;
using std::vector;
using std::ostream;
static void WriteAsOperandInternal(ostream &Out, const Value *V, bool PrintName,
map<const Type *, string> &TypeTable,
SlotCalculator *Table);
static const Module *getModuleFromVal(const Value *V) {
if (const Argument *MA = dyn_cast<const Argument>(V))
return MA->getParent() ? MA->getParent()->getParent() : 0;
else if (const BasicBlock *BB = dyn_cast<const BasicBlock>(V))
return BB->getParent() ? BB->getParent()->getParent() : 0;
else if (const Instruction *I = dyn_cast<const Instruction>(V)) {
const Function *M = I->getParent() ? I->getParent()->getParent() : 0;
return M ? M->getParent() : 0;
} else if (const GlobalValue *GV = dyn_cast<const GlobalValue>(V))
return GV->getParent();
return 0;
}
static SlotCalculator *createSlotCalculator(const Value *V) {
assert(!isa<Type>(V) && "Can't create an SC for a type!");
if (const Argument *FA = dyn_cast<const Argument>(V)) {
return new SlotCalculator(FA->getParent(), true);
} else if (const Instruction *I = dyn_cast<const Instruction>(V)) {
return new SlotCalculator(I->getParent()->getParent(), true);
} else if (const BasicBlock *BB = dyn_cast<const BasicBlock>(V)) {
return new SlotCalculator(BB->getParent(), true);
} else if (const GlobalVariable *GV = dyn_cast<const GlobalVariable>(V)){
return new SlotCalculator(GV->getParent(), true);
} else if (const Function *Func = dyn_cast<const Function>(V)) {
return new SlotCalculator(Func, true);
}
return 0;
}
// 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,
map<const Type *, string> &TypeNames) {
if (M && M->hasSymbolTable()) {
const SymbolTable *ST = M->getSymbolTable();
SymbolTable::const_iterator PI = ST->find(Type::TypeTy);
if (PI != ST->end()) {
SymbolTable::type_const_iterator I = PI->second.begin();
for (; I != PI->second.end(); ++I) {
// 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<const Type>(I->second);
if (!isa<PointerType>(Ty) ||
!cast<PointerType>(Ty)->getElementType()->isPrimitiveType())
TypeNames.insert(std::make_pair(Ty, "%"+I->first));
}
}
}
}
static string calcTypeName(const Type *Ty, vector<const Type *> &TypeStack,
map<const Type *, string> &TypeNames) {
if (Ty->isPrimitiveType()) return Ty->getDescription(); // Base case
// Check to see if the type is named.
map<const Type *, string>::iterator I = TypeNames.find(Ty);
if (I