//===-- Writer.cpp - Library for converting LLVM code to C ----------------===//
//
// This library implements the functionality defined in llvm/Assembly/CWriter.h
//
// TODO : Recursive types.
//
//===-----------------------------------------------------------------------==//
#include "llvm/Assembly/CWriter.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/iMemory.h"
#include "llvm/iTerminators.h"
#include "llvm/iPHINode.h"
#include "llvm/iOther.h"
#include "llvm/iOperators.h"
#include "llvm/SymbolTable.h"
#include "llvm/SlotCalculator.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/InstIterator.h"
#include "Support/StringExtras.h"
#include "Support/STLExtras.h"
#include <algorithm>
#include <set>
using std::string;
using std::map;
using std::ostream;
// Pass the Type* variable and and the variable name and this prints out the
// variable declaration.
//
static string calcTypeNameVar(const Type *Ty,
map<const Type *, string> &TypeNames,
const string &NameSoFar, bool ignoreName = false){
if (Ty->isPrimitiveType())
switch (Ty->getPrimitiveID()) {
case Type::VoidTyID: return "void " + NameSoFar;
case Type::BoolTyID: return "bool " + NameSoFar;
case Type::UByteTyID: return "unsigned char " + NameSoFar;
case Type::SByteTyID: return "signed char " + NameSoFar;
case Type::UShortTyID: return "unsigned short " + NameSoFar;
case Type::ShortTyID: return "short " + NameSoFar;
case Type::UIntTyID: return "unsigned " + NameSoFar;
case Type::IntTyID: return "int " + NameSoFar;
case Type::ULongTyID: return "unsigned long long " + NameSoFar;
case Type::LongTyID: return "signed long long " + NameSoFar;
case Type::FloatTyID: return "float " + NameSoFar;
case Type::DoubleTyID: return "double " + NameSoFar;
default :
std::cerr << "Unknown primitive type: " << Ty << "\n";
abort();
}
// Check to see if the type is named.
if (!ignoreName) {
map<const Type *, string>::iterator I = TypeNames.find(Ty);
if (I != TypeNames.end())
return I->second + " " + NameSoFar;
}
string Result;
switch (Ty->getPrimitiveID()) {
case Type::FunctionTyID: {
const FunctionType *MTy = cast<FunctionType>(Ty);
Result += calcTypeNameVar(MTy->getReturnType(), TypeNames, "");
Result += " " + NameSoFar + " (";
for (FunctionType::ParamTypes::const_iterator
I = MTy->getParamTypes().begin(),
E = MTy->getParamTypes().end(); I != E; ++I) {
if (I != MTy->getParamTypes().begin())
Result += ", ";
Result += calcTypeNameVar(*I, TypeNames, "");
}
if (MTy->isVarArg()) {
if (!MTy->getParamTypes().empty())
Result += ", ";
Result += "...";
}
return Result + ")";
}
case Type::StructTyID: {
const StructType *STy = cast<const StructType>(Ty);
Result = NameSoFar + " {\n";
unsigned indx = 0;
for (StructType::ElementTypes::const_iterator
I = STy->getElementTypes().begin(),
E = STy->getElementTypes().end(); I != E; ++I) {
Result += " " +calcTypeNameVar(*I, TypeNames, "field" + utostr(indx++));
Result += ";\n";
}
return Result + "}";
}
case Type::PointerTyID:
return calcTypeNameVar(cast<const PointerType>(Ty)->getElementType(),
TypeNames, "*" + NameSoFar);
case Type::ArrayTyID: {
const ArrayType *ATy = cast<const ArrayType>(Ty);
int NumElements = ATy->getNumElements();
return calcTypeNameVar(ATy->getElementType(), TypeNames,
NameSoFar + "[" + itostr(NumElements) + "]");
}
default:
assert(0 && "Unhandled case in getTypeProps!");
abort();
}
return Result;
}
namespace {
class CWriter : public InstVisitor<CWriter> {
ostream& Out;
SlotCalculator &Table;
const Module *TheModule;
map<const Type *, string> TypeNames;
std::set<const Value*> MangledGlobals;
public:
inline CWriter(ostream &o, SlotCalculator &Tab,