diff options
Diffstat (limited to 'lib/Target/CppBackend/CPPBackend.cpp')
-rw-r--r-- | lib/Target/CppBackend/CPPBackend.cpp | 1971 |
1 files changed, 1971 insertions, 0 deletions
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp new file mode 100644 index 0000000000..7e3c2ae449 --- /dev/null +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -0,0 +1,1971 @@ +//===-- CPPBackend.cpp - Library for converting LLVM code to C++ code -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the writing of the LLVM IR as a set of C++ calls to the +// LLVM IR interface. The input module is assumed to be verified. +// +//===----------------------------------------------------------------------===// + +#include "CPPTargetMachine.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instruction.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/PassManager.h" +#include "llvm/TypeSymbolTable.h" +#include "llvm/Target/TargetMachineRegistry.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Config/config.h" +#include <algorithm> +#include <iostream> +#include <set> + +using namespace llvm; + +static cl::opt<std::string> +FuncName("funcname", cl::desc("Specify the name of the generated function"), + cl::value_desc("function name")); + +enum WhatToGenerate { + GenProgram, + GenModule, + GenContents, + GenFunction, + GenFunctions, + GenInline, + GenVariable, + GenType +}; + +static cl::opt<WhatToGenerate> GenerationType(cl::Optional, + cl::desc("Choose what kind of output to generate"), + cl::init(GenProgram), + cl::values( + clEnumValN(GenProgram, "gen-program", "Generate a complete program"), + clEnumValN(GenModule, "gen-module", "Generate a module definition"), + clEnumValN(GenContents, "gen-contents", "Generate contents of a module"), + clEnumValN(GenFunction, "gen-function", "Generate a function definition"), + clEnumValN(GenFunctions,"gen-functions", "Generate all function definitions"), + clEnumValN(GenInline, "gen-inline", "Generate an inline function"), + clEnumValN(GenVariable, "gen-variable", "Generate a variable definition"), + clEnumValN(GenType, "gen-type", "Generate a type definition"), + clEnumValEnd + ) +); + +static cl::opt<std::string> NameToGenerate("for", cl::Optional, + cl::desc("Specify the name of the thing to generate"), + cl::init("!bad!")); + +namespace { + // Register the target. + RegisterTarget<CPPTargetMachine> X("cpp", " C++ backend"); + + typedef std::vector<const Type*> TypeList; + typedef std::map<const Type*,std::string> TypeMap; + typedef std::map<const Value*,std::string> ValueMap; + typedef std::set<std::string> NameSet; + typedef std::set<const Type*> TypeSet; + typedef std::set<const Value*> ValueSet; + typedef std::map<const Value*,std::string> ForwardRefMap; + + /// CppWriter - This class is the main chunk of code that converts an LLVM + /// module to a C++ translation unit. + class CppWriter : public ModulePass { + const char* progname; + std::ostream &Out; + const Module *TheModule; + uint64_t uniqueNum; + TypeMap TypeNames; + ValueMap ValueNames; + TypeMap UnresolvedTypes; + TypeList TypeStack; + NameSet UsedNames; + TypeSet DefinedTypes; + ValueSet DefinedValues; + ForwardRefMap ForwardRefs; + bool is_inline; + + public: + static char ID; + explicit CppWriter(std::ostream &o) : ModulePass((intptr_t)&ID), Out(o) {} + + virtual const char *getPassName() const { return "C++ backend"; } + + bool runOnModule(Module &M); + + bool doInitialization(Module &M) { + uniqueNum = 0; + is_inline = false; + + TypeNames.clear(); + ValueNames.clear(); + UnresolvedTypes.clear(); + TypeStack.clear(); + UsedNames.clear(); + DefinedTypes.clear(); + DefinedValues.clear(); + ForwardRefs.clear(); + + return false; + } + + void printProgram(const std::string& fname, const std::string& modName ); + void printModule(const std::string& fname, const std::string& modName ); + void printContents(const std::string& fname, const std::string& modName ); + void printFunction(const std::string& fname, const std::string& funcName ); + void printFunctions(); + void printInline(const std::string& fname, const std::string& funcName ); + void printVariable(const std::string& fname, const std::string& varName ); + void printType(const std::string& fname, const std::string& typeName ); + + void error(const std::string& msg); + + private: + void printLinkageType(GlobalValue::LinkageTypes LT); + void printVisibilityType(GlobalValue::VisibilityTypes VisTypes); + void printCallingConv(unsigned cc); + void printEscapedString(const std::string& str); + void printCFP(const ConstantFP* CFP); + + std::string getCppName(const Type* val); + inline void printCppName(const Type* val); + + std::string getCppName(const Value* val); + inline void printCppName(const Value* val); + + void printParamAttrs(const PAListPtr &PAL, const std::string &name); + bool printTypeInternal(const Type* Ty); + inline void printType(const Type* Ty); + void printTypes(const Module* M); + + void printConstant(const Constant *CPV); + void printConstants(const Module* M); + + void printVariableUses(const GlobalVariable *GV); + void printVariableHead(const GlobalVariable *GV); + void printVariableBody(const GlobalVariable *GV); + + void printFunctionUses(const Function *F); + void printFunctionHead(const Function *F); + void printFunctionBody(const Function *F); + void printInstruction(const Instruction *I, const std::string& bbname); + std::string getOpName(Value*); + + void printModuleBody(); + }; + + static unsigned indent_level = 0; + inline std::ostream& nl(std::ostream& Out, int delta = 0) { + Out << "\n"; + if (delta >= 0 || indent_level >= unsigned(-delta)) + indent_level += delta; + for (unsigned i = 0; i < indent_level; ++i) + Out << " "; + return Out; + } + + inline void in() { indent_level++; } + inline void out() { if (indent_level >0) indent_level--; } + + inline void + sanitize(std::string& str) { + for (size_t i = 0; i < str.length(); ++i) + if (!isalnum(str[i]) && str[i] != '_') + str[i] = '_'; + } + + inline std::string + getTypePrefix(const Type* Ty ) { + switch (Ty->getTypeID()) { + case Type::VoidTyID: return "void_"; + case Type::IntegerTyID: + return std::string("int") + utostr(cast<IntegerType>(Ty)->getBitWidth()) + + "_"; + case Type::FloatTyID: return "float_"; + case Type::DoubleTyID: return "double_"; + case Type::LabelTyID: return "label_"; + case Type::FunctionTyID: return "func_"; + case Type::StructTyID: return "struct_"; + case Type::ArrayTyID: return "array_"; + case Type::PointerTyID: return "ptr_"; + case Type::VectorTyID: return "packed_"; + case Type::OpaqueTyID: return "opaque_"; + default: return "other_"; + } + return "unknown_"; + } + + // Looks up the type in the symbol table and returns a pointer to its name or + // a null pointer if it wasn't found. Note that this isn't the same as the + // Mode::getTypeName function which will return an empty string, not a null + // pointer if the name is not found. + inline const std::string* + findTypeName(const TypeSymbolTable& ST, const Type* Ty) { + TypeSymbolTable::const_iterator TI = ST.begin(); + TypeSymbolTable::const_iterator TE = ST.end(); + for (;TI != TE; ++TI) + if (TI->second == Ty) + return &(TI->first); + return 0; + } + + void CppWriter::error(const std::string& msg) { + std::cerr << progname << ": " << msg << "\n"; + exit(2); + } + + // printCFP - Print a floating point constant .. very carefully :) + // This makes sure that conversion to/from floating yields the same binary + // result so that we don't lose precision. + void CppWriter::printCFP(const ConstantFP *CFP) { + APFloat APF = APFloat(CFP->getValueAPF()); // copy + if (CFP->getType() == Type::FloatTy) + APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven); + Out << "ConstantFP::get("; + if (CFP->getType() == Type::DoubleTy) + Out << "Type::DoubleTy, "; + else + Out << "Type::FloatTy, "; + Out << "APFloat("; +#if HAVE_PRINTF_A + char Buffer[100]; + sprintf(Buffer, "%A", APF.convertToDouble()); + if ((!strncmp(Buffer, "0x", 2) || + !strncmp(Buffer, "-0x", 3) || + !strncmp(Buffer, "+0x", 3)) && + APF.bitwiseIsEqual(APFloat(atof(Buffer)))) { + if (CFP->getType() == Type::DoubleTy) + Out << "BitsToDouble(" << Buffer << ")"; + else + Out << "BitsToFloat((float)" << Buffer << ")"; + Out << ")"; + } else { +#endif + std::string StrVal = ftostr(CFP->getValueAPF()); + + while (StrVal[0] == ' ') + StrVal.erase(StrVal.begin()); + + // Check to make sure that the stringized number is not some string like + // "Inf" or NaN. Check that the string matches the "[-+]?[0-9]" regex. + if (((StrVal[0] >= '0' && StrVal[0] <= '9') || + ((StrVal[0] == '-' || StrVal[0] == '+') && + (StrVal[1] >= '0' && StrVal[1] <= '9'))) && + (CFP->isExactlyValue(atof(StrVal.c_str())))) { + if (CFP->getType() == Type::DoubleTy) + Out << StrVal; + else + Out << StrVal << "f"; + } else if (CFP->getType() == Type::DoubleTy) + Out << "BitsToDouble(0x" << std::hex + << CFP->getValueAPF().convertToAPInt().getZExtValue() + << std::dec << "ULL) /* " << StrVal << " */"; + else + Out << "BitsToFloat(0x" << std::hex + << (uint32_t)CFP->getValueAPF().convertToAPInt().getZExtValue() + << std::dec << "U) /* " << StrVal << " */"; + Out << ")"; +#if HAVE_PRINTF_A + } +#endif + Out << ")"; + } + + void CppWriter::printCallingConv(unsigned cc){ + // Print the calling convention. + switch (cc) { + case CallingConv::C: Out << "CallingConv::C"; break; + case CallingConv::Fast: Out << "CallingConv::Fast"; break; + case CallingConv::Cold: Out << "CallingConv::Cold"; break; + case CallingConv::FirstTargetCC: Out << "CallingConv::FirstTargetCC"; break; + default: Out << cc; break; + } + } + + void CppWriter::printLinkageType(GlobalValue::LinkageTypes LT) { + switch (LT) { + case GlobalValue::InternalLinkage: + Out << "GlobalValue::InternalLinkage"; break; + case GlobalValue::LinkOnceLinkage: + Out << "GlobalValue::LinkOnceLinkage "; break; + case GlobalValue::WeakLinkage: + Out << "GlobalValue::WeakLinkage"; break; + case GlobalValue::AppendingLinkage: + Out << "GlobalValue::AppendingLinkage"; break; + case GlobalValue::ExternalLinkage: + Out << "GlobalValue::ExternalLinkage"; break; + case GlobalValue::DLLImportLinkage: + Out << "GlobalValue::DLLImportLinkage"; break; + case GlobalValue::DLLExportLinkage: + Out << "GlobalValue::DLLExportLinkage"; break; + case GlobalValue::ExternalWeakLinkage: + Out << "GlobalValue::ExternalWeakLinkage"; break; + case GlobalValue::GhostLinkage: + Out << "GlobalValue::GhostLinkage"; break; + } + } + + void CppWriter::printVisibilityType(GlobalValue::VisibilityTypes VisType) { + switch (VisType) { + default: assert(0 && "Unknown GVar visibility"); + case GlobalValue::DefaultVisibility: + Out << "GlobalValue::DefaultVisibility"; + break; + case GlobalValue::HiddenVisibility: + Out << "GlobalValue::HiddenVisibility"; + break; + case GlobalValue::ProtectedVisibility: + Out << "GlobalValue::ProtectedVisibility"; + break; + } + } + + // printEscapedString - Print each character of the specified string, escaping + // it if it is not printable or if it is an escape char. + void CppWriter::printEscapedString(const std::string &Str) { + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + unsigned char C = Str[i]; + if (isprint(C) && C != '"' && C != '\\') { + Out << C; + } else { + Out << "\\x" + << (char) ((C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A')) + << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A')); + } + } + } + + std::string CppWriter::getCppName(const Type* Ty) { + // First, handle the primitive types .. easy + if (Ty->isPrimitiveType() || Ty->isInteger()) { + switch (Ty->getTypeID()) { + case Type::VoidTyID: return "Type::VoidTy"; + case Type::IntegerTyID: { + unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth(); + return "IntegerType::get(" + utostr(BitWidth) + ")"; + } + case Type::FloatTyID: return "Type::FloatTy"; + case Type::DoubleTyID: return "Type::DoubleTy"; + case Type::LabelTyID: return "Type::LabelTy"; + default: + error("Invalid primitive type"); + break; + } + return "Type::VoidTy"; // shouldn't be returned, but make it sensible + } + + // Now, see if we've seen the type before and return that + TypeMap::iterator I = TypeNames.find(Ty); + if (I != TypeNames.end()) + return I->second; + + // Okay, let's build a new name for this type. Start with a prefix + const char* prefix = 0; + switch (Ty->getTypeID()) { + case Type::FunctionTyID: prefix = "FuncTy_"; break; + case Type::StructTyID: prefix = "StructTy_"; break; + case Type::ArrayTyID: prefix = "ArrayTy_"; break; + case Type::PointerTyID: prefix = "PointerTy_"; break; + case Type::OpaqueTyID: prefix = "OpaqueTy_"; break; + case Type::VectorTyID: prefix = "VectorTy_"; break; + default: prefix = "OtherTy_"; break; // prevent breakage + } + + // See if the type has a name in the symboltable and build accordingly + const std::string* tName = findTypeName(TheModule->getTypeSymbolTable(), Ty); + std::string name; + if (tName) + name = std::string(prefix) + *tName; + else + name = std::string(prefix) + utostr(uniqueNum++); + sanitize(name); + + // Save the name + return TypeNames[Ty] = name; + } + + void CppWriter::printCppName(const Type* Ty) { + printEscapedString(getCppName(Ty)); + } + + std::string CppWriter::getCppName(const Value* val) { + std::string name; + ValueMap::iterator I = ValueNames.find(val); + if (I != ValueNames.end() && I->first == val) + return I->second; + + if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(val)) { + name = std::string("gvar_") + + getTypePrefix(GV->getType()->getElementType()); + } else if (isa<Function>(val)) { + name = std::string("func_"); + } else if (const Constant* C = dyn_cast<Constant>(val)) { + name = std::string("const_") + getTypePrefix(C->getType()); + } else if (const Argument* Arg = dyn_cast<Argument>(val)) { + if (is_inline) { + unsigned argNum = std::distance(Arg->getParent()->arg_begin(), + Function::const_arg_iterator(Arg)) + 1; + name = std::string("arg_") + utostr(argNum); + NameSet::iterator NI = UsedNames.find(name); + if (NI != UsedNames.end()) + name += std::string("_") + utostr(uniqueNum++); + UsedNames.insert(name); + return ValueNames[val] = name; + } else { + name = getTypePrefix(val->getType()); + } + } else { + name = getTypePrefix(val->getType()); + } + name += (val->hasName() ? val->getName() : utostr(uniqueNum++)); + sanitize(name); + NameSet::iterator NI = UsedNames.find(name); + if (NI != UsedNames.end()) + name += std::string("_") + utostr(uniqueNum++); + UsedNames.insert(name); + return ValueNames[val] = name; + } + + void CppWriter::printCppName(const Value* val) { + printEscapedString(getCppName(val)); + } + + void CppWriter::printParamAttrs(const PAListPtr &PAL, + const std::string &name) { + Out << "PAListPtr " << name << "_PAL = 0;"; + nl(Out); + if (!PAL.isEmpty()) { + Out << '{'; in(); nl(Out); + Out << "SmallVector<ParamAttrsWithIndex, 4> Attrs;"; nl(Out); + Out << "ParamAttrsWithIndex PAWI;"; nl(Out); + for (unsigned i = 0; i < PAL.getNumSlots(); ++i) { + uint16_t index = PAL.getSlot(i).Index; + ParameterAttributes attrs = PAL.getSlot(i).Attrs; + Out << "PAWI.index = " << index << "; PAWI.attrs = 0 "; + if (attrs & ParamAttr::SExt) + Out << " | ParamAttr::SExt"; + if (attrs & ParamAttr::ZExt) + Out << " | ParamAttr::ZExt"; + if (attrs & ParamAttr::StructRet) + Out << " | ParamAttr::StructRet"; + if (attrs & ParamAttr::InReg) + Out << " | ParamAttr::InReg"; + if (attrs & ParamAttr::NoReturn) + Out << " | ParamAttr::NoReturn"; + if (attrs & ParamAttr::NoUnwind) + Out << " | ParamAttr::NoUnwind"; + if (attrs & ParamAttr::ByVal) + Out << " | ParamAttr::ByVal"; + if (attrs & ParamAttr::NoAlias) + Out << " | ParamAttr::NoAlias"; + if (attrs & ParamAttr::Nest) + Out << " | ParamAttr::Nest"; + if (attrs & ParamAttr::ReadNone) + Out << " | ParamAttr::ReadNone"; + if (attrs & ParamAttr::ReadOnly) + Out << " | ParamAttr::ReadOnly"; + Out << ";"; + nl(Out); + Out << "Attrs.push_back(PAWI);"; + nl(Out); + } + Out << name << "_PAL = PAListPtr::get(Attrs.begin(), Attrs.end());"; + nl(Out); + out(); nl(Out); + Out << '}'; nl(Out); + } + } + + bool CppWriter::printTypeInternal(const Type* Ty) { + // We don't print definitions for primitive types + if (Ty->isPrimitiveType() || Ty->isInteger()) + return false; + + // If we already defined this type, we don't need to define it again. + if (DefinedTypes.find(Ty) != DefinedTypes.end()) + return false; + + // Everything below needs the name for the type so get it now. + std::string typeName(getCppName(Ty)); + + // Search the type stack for recursion. If we find it, then generate this + // as an OpaqueType, but make sure not to do this multiple times because + // the type could appear in multiple places on the stack. Once the opaque + // definition is issued, it must not be re-issued. Consequently we have to + // check the UnresolvedTypes list as well. + TypeList::const_iterator TI = std::find(TypeStack.begin(), TypeStack.end(), + Ty); + if (TI != TypeStack.end()) { + TypeMap::const_iterator I = UnresolvedTypes.find(Ty); + if (I == UnresolvedTypes.end()) { + Out << "PATypeHolder " << typeName << "_fwd = OpaqueType::get();"; + nl(Out); + UnresolvedTypes[Ty] = typeName; + } + return true; + } + + // We're going to print a derived type which, by definition, contains other + // types. So, push this one we're printing onto the type stack to assist with + // recursive definitions. + TypeStack.push_back(Ty); + + // Print the type definition + switch (Ty->getTypeID()) { + case Type::FunctionTyID: { + const FunctionType* FT = cast<FunctionType>(Ty); + Out << "std::vector<const Type*>" << typeName << "_args;"; + nl(Out); + FunctionType::param_iterator PI = FT->param_begin(); + FunctionType::param_iterator PE = FT->param_end(); + for (; PI != PE; ++PI) { + const Type* argTy = static_cast<const Type*>(*PI); + bool isForward = printTypeInternal(argTy); + std::string argName(getCppName(argTy)); + Out << typeName << "_args.push_back(" << argName; + if (isForward) + Out << "_fwd"; + Out << ");"; + nl(Out); + } + bool isForward = printTypeInternal(FT->getReturnType()); + std::string retTypeName(getCppName(FT->getReturnType())); + Out << "FunctionType* " << typeName << " = FunctionType::get("; + in(); nl(Out) << "/*Result=*/" << retTypeName; + if (isForward) + Out << "_fwd"; + Out << ","; + nl(Out) << "/*Params=*/" << typeName << "_args,"; + nl(Out) << "/*isVarArg=*/" << (FT->isVarArg() ? "true" : "false") << ");"; + out(); + nl(Out); + break; + } + case Type::StructTyID: { + const StructType* ST = cast<StructType>(Ty); + Out << "std::vector<const Type*>" << typeName << "_fields;"; + nl(Out); + StructType::element_iterator EI = ST->element_begin(); + StructType::element_iterator EE = ST->element_end(); + for (; EI != EE; ++EI) { + const Type* fieldTy = static_cast<const Type*>(*EI); + bool isForward = printTypeInternal(fieldTy); + std::string fieldName(getCppName(fieldTy)); + Out << typeName << "_fields.push_back(" << fieldName; + if (isForward) + Out << "_fwd"; + Out << ");"; + nl(Out); + } + Out << "StructType* " << typeName << " = StructType::get(" + << typeName << "_fields, /*isPacked=*/" + << (ST->isPacked() ? "true" : "false") << ");"; + nl(Out); + break; + } + case Type::ArrayTyID: { + const ArrayType* AT = cast<ArrayType>(Ty); + const Type* ET = AT->getElementType(); + bool isForward = printTypeInternal(ET); + std::string elemName(getCppName(ET)); + Out << "ArrayType* " << typeName << " = ArrayType::get(" + << elemName << (isForward ? "_fwd" : "") + << ", " << utostr(AT->getNumElements()) << ");"; + nl(Out); + break; + } + case Type::PointerTyID: { + const PointerType* PT = cast<PointerType>(Ty); + const Type* ET = PT->getElementType(); + bool isForward = printTypeInternal(ET); + std::string elemName(getCppName(ET)); + Out << "PointerType* " << typeName << " = PointerType::get(" + << elemName << (isForward ? "_fwd" : "") + << ", " << utostr(PT->getAddressSpace()) << ");"; + nl(Out); + break; + } + case Type::VectorTyID: { + const VectorType* PT = cast<VectorType>(Ty); + const Type* ET = PT->getElementType(); + bool isForward = printTypeInternal(ET); + std::string elemName(getCppName(ET)); + Out << "VectorType* " << typeName << " = VectorType::get(" + << elemName << (isForward ? "_fwd" : "") + << ", " << utostr(PT->getNumElements()) << ");"; + nl(Out); + break; + } + case Type::OpaqueTyID: { + Out << "OpaqueType* " << typeName << " = OpaqueType::get();"; + nl(Out); + break; + } + default: + error("Invalid TypeID"); + } + + // If the type had a name, make sure we recreate it. + const std::string* progTypeName = + findTypeName(TheModule->getTypeSymbolTable(),Ty); + if (progTypeName) { + Out << "mod->addTypeName(\"" << *progTypeName << "\", " + << typeName << ");"; + nl(Out); + } + + // Pop us off the type stack + TypeStack.pop_back(); + + // Indicate that this type is now defined. + DefinedTypes.insert(Ty); + + // Early resolve as many unresolved types as possible. Search the unresolved + // types map for the type we just printed. Now that its definition is complete + // we can resolve any previous references to it. This prevents a cascade of + // unresolved types. + TypeMap::iterator I = UnresolvedTypes.find(Ty); + if (I != UnresolvedTypes.end()) { + Out << "cast<OpaqueType>(" << I->second + << "_fwd.get())->refineAbstractTypeTo(" << I->second << ");"; + nl(Out); + Out << I->second << " = cast<"; + switch (Ty->getTypeID()) { + case Type::FunctionTyID: Out << "FunctionType"; break; + case Type::ArrayTyID: Out << "ArrayType"; break; + case Type::StructTyID: Out << "StructType"; break; + case Type::VectorTyID: Out << "VectorType"; break; + case Type::PointerTyID: Out << "PointerType"; break; + case Type::OpaqueTyID: Out << "OpaqueType"; break; + default: Out << "NoSuchDerivedType"; break; + } + Out << ">(" << I->second << "_fwd.get());"; + nl(Out); nl(Out); + UnresolvedTypes.erase(I); + } + + // Finally, separate the type definition from other with a newline. + nl(Out); + + // We weren't a recursive type + return false; + } + + // Prints a type definition. Returns true if it could not resolve all the + // types in the definition but had to use a forward reference. + void CppWriter::printType(const Type* Ty) { + assert(TypeStack.empty()); + TypeStack.clear(); + printTypeInternal(Ty); + assert(TypeStack.empty()); + } + + void CppWriter::printTypes(const Module* M) { + // Walk the symbol table and print out all its types + const TypeSymbolTable& symtab = M->getTypeSymbolTable(); + for (TypeSymbolTable::const_iterator TI = symtab.begin(), TE = symtab.end(); + TI != TE; ++TI) { + + // For primitive types and types already defined, just add a name + TypeMap::const_iterator TNI = TypeNames.find(TI->second); + if (TI->second->isInteger() || TI->second->isPrimitiveType() || + TNI != TypeNames.end()) { + Out << "mod->addTypeName(\""; + printEscapedString(TI->first); + Out << "\", " << getCppName(TI->second) << ");"; + nl(Out); + // For everything else, define the type + } else { + printType(TI->second); + } + } + + // Add all of the global variables to the value table... + for (Module::const_global_iterator I = TheModule->global_begin(), + E = TheModule->global_end(); I != E; ++I) { + if (I->hasInitializer()) + printType(I->getInitializer()->getType()); + printType(I->getType()); + } + + // Add all the functions to the table + for (Module::const_iterator FI = TheModule->begin(), FE = TheModule->end(); + FI != FE; ++FI) { + printType(FI->getReturnType()); + printType(FI->getFunctionType()); + // Add all the function arguments + for (Function::const_arg_iterator AI = FI->arg_begin(), + AE = FI->arg_end(); AI != AE; ++AI) { + printType(AI->getType()); + } + + // Add all of the basic blocks and instructions + for (Function::const_iterator BB = FI->begin(), + E = FI->end(); BB != E; ++BB) { + printType(BB->getType()); + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; + ++I) { + printType(I->getType()); + for (unsigned i = 0; i < I->getNumOperands(); ++i) + printType(I->getOperand(i)->getType()); + } + } + } + } + + + // printConstant - Print out a constant pool entry... + void CppWriter::printConstant(const Constant *CV) { + // First, if the constant is actually a GlobalValue (variable or function) + // or its already in the constant list then we've printed it already and we + // can just return. + if (isa<GlobalValue>(CV) || ValueNames.find(CV) != ValueNames.end()) + return; + + std::string constName(getCppName(CV)); + std::string typeName(getCppName(CV->getType())); + if (CV->isNullValue()) { + Out << "Constant* " << constName << " = Constant::getNullValue(" + << typeName << ");"; + nl(Out); + return; + } + if (isa<GlobalValue>(CV)) { + // Skip variables and functions, we emit them elsewhere + return; + } + if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { + Out << "ConstantInt* " << constName << " = ConstantInt::get(APInt(" + << cast<IntegerType>(CI->getType())->getBitWidth() << ", " + << " \"" << CI->getValue().toStringSigned(10) << "\", 10));"; + } else if (isa<ConstantAggregateZero>(CV)) { + Out << "ConstantAggregateZero* " << constName + << " = ConstantAggregateZero::get(" << typeName << ");"; + } else if (isa<ConstantPointerNull>(CV)) { + Out << "ConstantPointerNull* " << constName + << " = ConstanPointerNull::get(" << typeName << ");"; + } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) { + Out << "ConstantFP* " << constName << " = "; + printCFP(CFP); + Out << ";"; + } else if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) { + if (CA->isString() && CA->getType()->getElementType() == Type::Int8Ty) { + Out << "Constant* " << constName << " = ConstantArray::get(\""; + std::string tmp = CA->getAsString(); + bool nullTerminate = false; + if (tmp[tmp.length()-1] == 0) { + tmp.erase(tmp.length()-1); + nullTerminate = true; + } + printEscapedString(tmp); + // Determine if we want null termination or not. + if (nullTerminate) + Out << "\", true"; // Indicate that the null terminator should be + // added. + else + Out << "\", false";// No null terminator + Out << ");"; + } else { + Out << "std::vector<Constant*> " << constName << "_elems;"; + nl(Out); + unsigned N = CA->getNumOperands(); + for (unsigned i = 0; i < N; ++i) { + printConstant(CA->getOperand(i)); // recurse to print operands + Out << constName << "_elems.push_back(" + << getCppName(CA->getOperand(i)) << ");"; + nl(Out); + } + Out << "Constant* " << constName << " = ConstantArray::get(" + << typeName << ", " << constName << "_elems);"; + } + } else if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(CV)) { + Out << "std::vector<Constant*> " << constName << "_fields;"; + nl(Out); + unsigned N = CS->getNumOperands(); + for (unsigned i = 0; i < N; i++) { + printConstant(CS->getOperand(i)); + Out << constName << "_fields.push_back(" + << getCppName(CS->getOperand(i)) << ");"; + nl(Out); + } + Out << "Constant* " << constName << " = ConstantStruct::get(" + << typeName << ", " << constName << "_fields);"; + } else if (const ConstantVector *CP = dyn_cast<ConstantVector>(CV)) { + Out << "std::vector<Constant*> " << constName << "_elems;"; + nl(Out); + unsigned N = CP->getNumOperands(); + for (unsigned i = 0; i < N; ++i) { + printConstant(CP->getOperand(i)); + Out << constName << "_elems.push_back(" + << getCppName(CP->getOperand(i)) << ");"; + nl(Out); + } + Out << "Constant* " << constName << " = ConstantVector::get(" + << typeName << ", " << constName << "_elems);"; + } else if (isa<UndefValue>(CV)) { + Out << "UndefValue* " << constName << " = UndefValue::get(" + << typeName << ");"; + } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { + if (CE->getOpcode() == Instruction::GetElementPtr) { + Out << "std::vector<Constant*> " << constName << "_indices;"; + nl(Out); + printConstant(CE->getOperand(0)); + for (unsigned i = 1; i < CE->getNumOperands(); ++i ) { + printConstant(CE->getOperand(i)); + Out << constName << "_indices.push_back(" + << getCppName(CE->getOperand(i)) << ");"; + nl(Out); + } + Out << "Constant* " << constName + << " = ConstantExpr::getGetElementPtr(" + << getCppName(CE->getOperand(0)) << ", " + << "&" << constName << "_indices[0], " + << constName << "_indices.size()" + << " );"; + } else if (CE->isCast()) { + printConstant(CE->getOperand(0)); + Out << "Constant* " << constName << " = ConstantExpr::getCast("; + switch (CE->getOpcode()) { + default: assert(0 && "Invalid cast opcode"); + case Instruction::Trunc: Out << "Instruction::Trunc"; break; + case Instruction::ZExt: Out << "Instruction::ZExt"; break; + case Instruction::SExt: Out << "Instruction::SExt"; break; + case Instruction::FPTrunc: Out << "Instruction::FPTrunc"; break; + case Instruction::FPExt: Out << "Instruction::FPExt"; break; + case Instruction::FPToUI: Out << "Instruction::FPToUI"; break; + case Instruction::FPToSI: Out << "Instruction::FPToSI"; break; + case Instruction::UIToFP: Out << "Instruction::UIToFP"; break; + case Instruction::SIToFP: Out << "Instruction::SIToFP"; break; + case Instruction::PtrToInt: Out << "Instruction::PtrToInt"; break; + case Instruction::IntToPtr: Out << "Instruction::IntToPtr"; break; + case Instruction::BitCast: Out << "Instruction::BitCast"; break; + } + Out << ", " << getCppName(CE->getOperand(0)) << ", " + << getCppName(CE->getType()) << ");"; + } else { + unsigned N = CE->getNumOperands(); + for (unsigned i = 0; i < N; ++i ) { + printConstant(CE->getOperand(i)); + } + Out << "Constant* " << constName << " = ConstantExpr::"; + switch (CE->getOpcode()) { + case Instruction::Add: Out << "getAdd("; break; + case Instruction::Sub: Out << "getSub("; break; + case Instruction::Mul: Out << "getMul("; break; + case Instruction::UDiv: Out << "getUDiv("; break; + case Instruction::SDiv: Out << "getSDiv("; break; + case Instruction::FDiv: Out << "getFDiv("; break; + case Instruction::URem: Out << "getURem("; break; + case Instruction::SRem: Out << "getSRem("; break; + case Instruction::FRem: Out << "getFRem("; break; + case Instruction::And: Out << "getAnd("; break; + case Instruction::Or: Out << "getOr("; break; + case Instruction::Xor: Out << "getXor("; break; + case Instruction::ICmp: + Out << "getICmp(ICmpInst::ICMP_"; + switch (CE->getPredicate()) { + case ICmpInst::ICMP_EQ: Out << "EQ"; break; + case ICmpInst::ICMP_NE: Out << "NE"; break; + case ICmpInst::ICMP_SLT: Out << "SLT"; break; + case ICmpInst::ICMP_ULT: Out << "ULT"; break; + case ICmpInst::ICMP_SGT: Out << "SGT"; break; + case ICmpInst::ICMP_UGT: Out << "UGT"; break; + case ICmpInst::ICMP_SLE: Out << "SLE"; break; + case ICmpInst::ICMP_ULE: Out << "ULE"; break; + case ICmpInst::ICMP_SGE: Out << "SGE"; break; + case ICmpInst::ICMP_UGE: Out << "UGE"; break; + default: error("Invalid ICmp Predicate"); + } + break; + case Instruction::FCmp: |