diff options
-rw-r--r-- | docs/CommandGuide/llvm2cpp.pod | 217 | ||||
-rw-r--r-- | tools/llvm2cpp/CppWriter.cpp | 1968 | ||||
-rw-r--r-- | tools/llvm2cpp/CppWriter.h | 18 | ||||
-rw-r--r-- | tools/llvm2cpp/Makefile | 15 | ||||
-rw-r--r-- | tools/llvm2cpp/llvm2cpp.cpp | 122 |
5 files changed, 0 insertions, 2340 deletions
diff --git a/docs/CommandGuide/llvm2cpp.pod b/docs/CommandGuide/llvm2cpp.pod deleted file mode 100644 index 4b86ae0fea..0000000000 --- a/docs/CommandGuide/llvm2cpp.pod +++ /dev/null @@ -1,217 +0,0 @@ -=pod - -=head1 NAME - -llvm2xpp - LLVM bitcode to LLVM C++ IR translator - -=head1 SYNOPSIS - -B<llvm2cpp> [I<options>] [I<filename>] - -=head1 DESCRIPTION - -B<llvm2cpp> translates from LLVM bitcode (.bc files) to a -corresponding C++ source file that will make calls against the LLVM C++ API to -build the same module as the input. By default, the C++ output is a complete -program that builds the module, verifies it and then emits the module as -LLVM assembly. This technique assists with testing because the input to -B<llvm2cpp> and the output of the generated C++ program should be identical. - -If F<filename> is omitted or is C<->, then B<llvm2cpp> reads its input from -standard input. - -If an output file is not specified with the B<-o> option, then -B<llvm2cpp> sends its output to a file or standard output by following -these rules: - -=over - -=item * - -If the input is standard input, then the output is standard output. - -=item * - -If the input is a file that ends with C<.bc>, then the output file is of -the same name, except that the suffix is changed to C<.cpp>. - -=item * - -If the input is a file that does not end with the C<.bc> suffix, then the -output file has the same name as the input file, except that the C<.cpp> -suffix is appended. - -=back - -=head1 OPTIONS - -=over - -=item B<-f> - -Force overwrite. Normally, B<llvm2cpp> will refuse to overwrite an -output file that already exists. With this option, B<llvm2cpp> -will overwrite the output file and replace it with new C++ source code. - -=item B<--help> - -Print a summary of command line options. - -=item B<-f> - -Normally, B<llvm2cpp> will not overwrite an existing output file. With this -option, that default behavior is changed and the program will overwrite existing -output files. - -=item B<-o> F<filename> - -Specify the output file name. If F<filename> is C<->, then B<llvm2cpp> -sends its output to standard output. - -=item B<-funcname> F<functionName> - -Specify the name of the function to be generated. The generated code contains a -single function that produces the input module. By default its name is -I<makeLLVMModule>. The B<-funcname> option overrides this default and allows -you to control the name of the generated function. This is handy in conjunction -with the B<-fragment> option when you only want B<llvm2cpp> to generate a -single function that produces the module. With both options, such generated code -could be I<#included> into another program. - -=item B<-for> - -Specify the name of the thing for which C++ code should be generated. By default -the entire input module is re-generated. However, use of the various B<-gen-*> -options can restrict what is produced. This option indicates what that -restriction is. - -=item B<-gen-program> - -Specify that the output should be a complete program. Such program will recreate -B<llvm2cpp>'s input as an LLVM module, verify that module, and then write out -the module in LLVM assembly format. This is useful for doing identity tests -where the output of the generated program is identical to the input to -B<llvm2cpp>. The LLVM DejaGnu test suite can make use of this fact. This is the -default form of generated output. - -If the B<-for> option is given with this option, it specifies the module -identifier to use for the module created. - -=item B<-gen-module> - -Specify that the output should be a function that regenerates the module. It is -assumed that this output will be #included into another program that has already -arranged for the correct header files to be #included. The function generated -takes no arguments and returns a I<Module*>. - -If the B<-for> option is given with this option, it specifies the module -identifier to use in creating the module returned by the generated function. - -=item B<-gen-contents> - -Specify that the output should be a function that adds the contents of the input -module to another module. It is assumed that the output will be #included into -another program that has already arranged for the correct header files to be -#included. The function generated takes a single argument of type I<Module*> and -returns that argument. Note that Module level attributes such as endianess, -pointer size, target triple and inline asm are not passed on from the input -module to the destination module. Only the sub-elements of the module (types, -constants, functions, global variables) will be added to the input module. - -If the B<-for> option is given with this option, it specifies the module -identifier to set in the input module by the generated function. - -=item B<-gen-function> - -Specify that the output should be a function that produces the definitions -necessary for a specific function to be added to a module. It is assumed that -the output will be #included into another program that has already arranged -for the correct header files to be #included. The function generated takes a -single argument of type I<Module*> and returns the I<Function*> that it added to -the module. Note that only those things (types, constants, etc.) directly -needed in the definition of the function will be placed in the generated -function. - -The B<-for> option must be given with this option or an error will be produced. -The value of the option must be the name of a function in the input module for -which code should be generated. If the named function does not exist an error -will be produced. - -=item B<-gen-inline> - -This option is very analagous to B<-gen-function> except that the generated -function will not re-produce the target function's definition. Instead, the body -of the target function is inserted into some other function passed as an -argument to the generated function. Similarly any arguments to the function must -be passed to the generated function. The result of the generated function is the -first basic block of the target function. - -The B<-for> option works the same way as it does for B<-gen-function>. - -=item B<-gen-variable> - -Specify that the output should be a function that produces the definitions -necessary for a specific global variable to be added to a module. It is assumed -that the output will be #included into another program that has already arranged -for the correct header files to be #included. The function generated takes a -single argument of type I<Module*> and returns the I<GlobalVariable*> that it -added to the module. Note that only those things (types, constants, etc.) -directly needed in the definition of the global variable will be placed in the -generated function. - -The B<-for> option must be given with this option or an error will be produced. -THe value of the option must be the name of a global variable in the input -module for which code should be generated. If the named global variable does not -exist an error will be produced. - -=item B<-gen-type> - -Specify that the output should be a function that produces the definitions -necessary for specific type to be added to a module. It is assumed that the -otuput will be #included into another program that has already arranged for the -correct header files to be #included. The function generated take a single -argument of type I<Module*> and returns the I<Type*> that it added to the -module. Note that the generated function will only add the necessary type -definitions to (possibly recursively) define the requested type. - -The B<-for> option must be given with this option or an error will be produced. -The value of the option must be the name of a global type in the input module -for which code should be generated. If the named type does not exist an error -will be produced. - -=item B<-stats> - -Show pass statistics (not interesting in this program). - -=item B<-time-passes> - -Show pass timing statistics (not interesting in this program). - -=item B<-version> - -Show the version number of this program. - -=back - - -=head1 EXIT STATUS - -If B<llvm2cpp> succeeds, it will exit with 0. Otherwise, if an error -occurs, it will exit with a non-zero value. - -=head1 SEE ALSO - -L<llvm-as|llvm-as> L<tblgen|tblgen> - -=head1 NOTES - -This tool may be removed from a future version of LLVM. Instead, its -functionality may be incorporated into the llc tool. It would then act similarly -to other targets except its output would be C++ source that could be compiled to -construct the input program. - -=head1 AUTHORS - -Written by Reid Spencer (L<http://hlvm.org>). - -=cut diff --git a/tools/llvm2cpp/CppWriter.cpp b/tools/llvm2cpp/CppWriter.cpp deleted file mode 100644 index b724b9c871..0000000000 --- a/tools/llvm2cpp/CppWriter.cpp +++ /dev/null @@ -1,1968 +0,0 @@ -//===-- CppWriter.cpp - Printing LLVM IR as a C++ Source File -------------===// -// -// 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 "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/TypeSymbolTable.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 { -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; - -class CppWriter { - 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: - inline CppWriter(std::ostream &o, const Module *M, const char* pn="llvm2cpp") - : progname(pn), Out(o), TheModule(M), uniqueNum(0), TypeNames(), - ValueNames(), UnresolvedTypes(), TypeStack(), is_inline(false) { } - - const Module* getModule() { return TheModule; } - - 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()); |