llvm-6502/tools/llvm2cpp/CppWriter.cpp
Reid Spencer 3ed469ccd7 For PR786:
Turn on -Wunused and -Wno-unused-parameter. Clean up most of the resulting
fall out by removing unused variables. Remaining warnings have to do with
unused functions (I didn't want to delete code without review) and unused
variables in generated code. Maintainers should clean up the remaining
issues when they see them. All changes pass DejaGnu tests and Olden.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31380 91177308-0d34-0410-b5e6-96231b3b80d8
2006-11-02 20:25:50 +00:00

1754 lines
60 KiB
C++

//===-- CppWriter.cpp - Printing LLVM IR as a C++ Source File -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and 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/SymbolTable.h"
#include "llvm/Support/CFG.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/CommandLine.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,
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(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 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 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);
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 const char*
getTypePrefix(const Type* Ty ) {
const char* prefix;
switch (Ty->getTypeID()) {
case Type::VoidTyID: prefix = "void_"; break;
case Type::BoolTyID: prefix = "bool_"; break;
case Type::UByteTyID: prefix = "ubyte_"; break;
case Type::SByteTyID: prefix = "sbyte_"; break;
case Type::UShortTyID: prefix = "ushort_"; break;
case Type::ShortTyID: prefix = "short_"; break;
case Type::UIntTyID: prefix = "uint_"; break;
case Type::IntTyID: prefix = "int_"; break;
case Type::ULongTyID: prefix = "ulong_"; break;
case Type::LongTyID: prefix = "long_"; break;
case Type::FloatTyID: prefix = "float_"; break;
case Type::DoubleTyID: prefix = "double_"; break;
case Type::LabelTyID: prefix = "label_"; break;
case Type::FunctionTyID: prefix = "func_"; break;
case Type::StructTyID: prefix = "struct_"; break;
case Type::ArrayTyID: prefix = "array_"; break;
case Type::PointerTyID: prefix = "ptr_"; break;
case Type::PackedTyID: prefix = "packed_"; break;
case Type::OpaqueTyID: prefix = "opaque_"; break;
default: prefix = "other_"; break;
}
return prefix;
}
// 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 SymbolTable& ST, const Type* Ty)
{
SymbolTable::type_const_iterator TI = ST.type_begin();
SymbolTable::type_const_iterator TE = ST.type_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) {
Out << "ConstantFP::get(";
if (CFP->getType() == Type::DoubleTy)
Out << "Type::DoubleTy, ";
else
Out << "Type::FloatTy, ";
#if HAVE_PRINTF_A
char Buffer[100];
sprintf(Buffer, "%A", CFP->getValue());
if ((!strncmp(Buffer, "0x", 2) ||
!strncmp(Buffer, "-0x", 3) ||
!strncmp(Buffer, "+0x", 3)) &&
(atof(Buffer) == CFP->getValue()))
if (CFP->getType() == Type::DoubleTy)
Out << "BitsToDouble(" << Buffer << ")";
else
Out << "BitsToFloat(" << Buffer << ")";
else {
#endif
std::string StrVal = ftostr(CFP->getValue());
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'))) &&
(atof(StrVal.c_str()) == CFP->getValue()))
if (CFP->getType() == Type::DoubleTy)
Out << StrVal;
else
Out << StrVal;
else if (CFP->getType() == Type::DoubleTy)
Out << "BitsToDouble(0x" << std::hex << DoubleToBits(CFP->getValue())
<< std::dec << "ULL) /* " << StrVal << " */";
else
Out << "BitsToFloat(0x" << std::hex << FloatToBits(CFP->getValue())
<< std::dec << "U) /* " << StrVal << " */";
#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::CSRet: Out << "CallingConv::CSRet"; 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;
}
}
// 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()) {
switch (Ty->getTypeID()) {
case Type::VoidTyID: return "Type::VoidTy";
case Type::BoolTyID: return "Type::BoolTy";
case Type::UByteTyID: return "Type::UByteTy";
case Type::SByteTyID: return "Type::SByteTy";
case Type::UShortTyID: return "Type::UShortTy";
case Type::ShortTyID: return "Type::ShortTy";
case Type::UIntTyID: return "Type::UIntTy";
case Type::IntTyID: return "Type::IntTy";
case Type::ULongTyID: return "Type::ULongTy";
case Type::LongTyID: return "Type::LongTy";
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::PackedTyID: prefix = "PackedTy_"; 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->getSymbolTable(), 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));
}
bool
CppWriter::printTypeInternal(const Type* Ty) {
// We don't print definitions for primitive types
if (Ty->isPrimitiveType())
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);";
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" : "") << ");";
nl(Out);
break;
}
case Type::PackedTyID: {
const PackedType* PT = cast<PackedType>(Ty);
const Type* ET = PT->getElementType();
bool isForward = printTypeInternal(ET);
std::string elemName(getCppName(ET));
Out << "PackedType* " << typeName << " = PackedType::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->getSymbolTable(),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::PackedTyID: Out << "PackedType"; 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 SymbolTable& symtab = M->getSymbolTable();
for (SymbolTable::type_const_iterator TI = symtab.type_begin(),
TE = symtab.type_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->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 ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
Out << "ConstantBool* " << constName << " = ConstantBool::get("
<< (CB->getValue() ? "true" : "false") << ");";
} else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
Out << "ConstantInt* " << constName << " = ConstantInt::get("
<< typeName << ", "
<< (CV->getType()->isSigned() ? CI->getSExtValue() : CI->getZExtValue())
<< ");";
} 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::SByteTy) {
Out << "Constant* " << constName << " = ConstantArray::get(\"";
printEscapedString(CA->getAsString());
// Determine if we want null termination or not.
if (CA->getType()->getNumElements() <= CA->getAsString().length())
Out << "\", false";// No null terminator
else
Out << "\", true"; // Indicate that the null terminator should be added.
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 ConstantPacked *CP = dyn_cast<ConstantPacked>(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 << " = ConstantPacked::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);";
} else if (CE->getOpcode() == Instruction::Cast) {
printConstant(CE->getOperand(0));
Out << "Constant* " << constName << " = ConstantExpr::getCast(";
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::SetEQ: Out << "getSetEQ"; break;
case Instruction::SetNE: Out << "getSetNE"; break;
case Instruction::SetLE: Out << "getSetLE"; break;
case Instruction::SetGE: Out << "getSetGE"; break;
case Instruction::SetLT: Out << "getSetLT"; break;
case Instruction::SetGT: Out << "getSetGT"; break;
case Instruction::Shl: Out << "getShl"; break;
case Instruction::Shr: Out << "getShr"; break;
case Instruction::Select: Out << "getSelect"; break;
case Instruction::ExtractElement: Out << "getExtractElement"; break;
case Instruction::InsertElement: Out << "getInsertElement"; break;
case Instruction::ShuffleVector: Out << "getShuffleVector"; break;
default:
error("Invalid constant expression");
break;
}
Out << getCppName(CE->getOperand(0));
for (unsigned i = 1; i < CE->getNumOperands(); ++i)
Out << ", " << getCppName(CE->getOperand(i));
Out << ");";
}
} else {
error("Bad Constant");
Out << "Constant* " << constName << " = 0; ";
}
nl(Out);
}
void
CppWriter::printConstants(const Module* M) {
// Traverse all the global variables looking for constant initializers
for (Module::const_global_iterator I = TheModule->global_begin(),
E = TheModule->global_end(); I != E; ++I)
if (I->hasInitializer())
printConstant(I->getInitializer());
// Traverse the LLVM functions looking for constants
for (Module::const_iterator FI = TheModule->begin(), FE = TheModule->end();
FI != FE; ++FI) {
// Add all of the basic blocks and instructions
for (Function::const_iterator BB = FI->begin(),
E = FI->end(); BB != E; ++BB) {
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;
++I) {
for (unsigned i = 0; i < I->getNumOperands(); ++i) {
if (Constant* C = dyn_cast<Constant>(I->getOperand(i))) {
printConstant(C);
}
}
}
}
}
}
void CppWriter::printVariableUses(const GlobalVariable *GV) {
nl(Out) << "// Type Definitions";
nl(Out);
printType(GV->getType());
if (GV->hasInitializer()) {
Constant* Init = GV->getInitializer();
printType(Init->getType());
if (Function* F = dyn_cast<Function>(Init)) {
nl(Out)<< "/ Function Declarations"; nl(Out);
printFunctionHead(F);
} else if (GlobalVariable* gv = dyn_cast<GlobalVariable>(Init)) {
nl(Out) << "// Global Variable Declarations"; nl(Out);
printVariableHead(gv);
} else {
nl(Out) << "// Constant Definitions"; nl(Out);
printConstant(gv);
}
if (GlobalVariable* gv = dyn_cast<GlobalVariable>(Init)) {
nl(Out) << "// Global Variable Definitions"; nl(Out);
printVariableBody(gv);
}
}
}
void CppWriter::printVariableHead(const GlobalVariable *GV) {
nl(Out) << "GlobalVariable* " << getCppName(GV);
if (is_inline) {
Out << " = mod->getGlobalVariable(";
printEscapedString(GV->getName());
Out << ", " << getCppName(GV->getType()->getElementType()) << ",true)";
nl(Out) << "if (!" << getCppName(GV) << ") {";
in(); nl(Out) << getCppName(GV);
}
Out << " = new GlobalVariable(";
nl(Out) << "/*Type=*/";
printCppName(GV->getType()->getElementType());
Out << ",";
nl(Out) << "/*isConstant=*/" << (GV->isConstant()?"true":"false");
Out << ",";
nl(Out) << "/*Linkage=*/";
printLinkageType(GV->getLinkage());
Out << ",";
nl(Out) << "/*Initializer=*/0, ";
if (GV->hasInitializer()) {
Out << "// has initializer, specified below";
}
nl(Out) << "/*Name=*/\"";
printEscapedString(GV->getName());
Out << "\",";
nl(Out) << "mod);";
nl(Out);
if (GV->hasSection()) {
printCppName(GV);
Out << "->setSection(\"";
printEscapedString(GV->getSection());
Out << "\");";
nl(Out);
}
if (GV->getAlignment()) {
printCppName(GV);
Out << "->setAlignment(" << utostr(GV->getAlignment()) << ");";
nl(Out);
};
if (is_inline) {
out(); Out << "}"; nl(Out);
}
}
void
CppWriter::printVariableBody(const GlobalVariable *GV) {
if (GV->hasInitializer()) {
printCppName(GV);
Out << "->setInitializer(";
//if (!isa<GlobalValue(GV->getInitializer()))
//else
Out << getCppName(GV->getInitializer()) << ");";
nl(Out);
}
}
std::string
CppWriter::getOpName(Value* V) {
if (!isa<Instruction>(V) || DefinedValues.find(V) != DefinedValues.end())
return getCppName(V);
// See if its alread in the map of forward references, if so just return the
// name we already set up for it
ForwardRefMap::const_iterator I = ForwardRefs.find(V);
if (I != ForwardRefs.end())
return I->second;
// This is a new forward reference. Generate a unique name for it
std::string result(std::string("fwdref_") + utostr(uniqueNum++));
// Yes, this is a hack. An Argument is the smallest instantiable value that
// we can make as a placeholder for the real value. We'll replace these
// Argument instances later.
Out << "Argument* " << result << " = new Argument("
<< getCppName(V->getType()) << ");";
nl(Out);
ForwardRefs[V] = result;
return result;
}
// printInstruction - This member is called for each Instruction in a function.
void
CppWriter::printInstruction(const Instruction *I, const std::string& bbname) {
std::string iName(getCppName(I));
// Before we emit this instruction, we need to take care of generating any
// forward references. So, we get the names of all the operands in advance
std::string* opNames = new std::string[I->getNumOperands()];
for (unsigned i = 0; i < I->getNumOperands(); i++) {
opNames[i] = getOpName(I->getOperand(i));
}
switch (I->getOpcode()) {
case Instruction::Ret: {
const ReturnInst* ret = cast<ReturnInst>(I);
Out << "ReturnInst* " << iName << " = new ReturnInst("
<< (ret->getReturnValue() ? opNames[0] + ", " : "") << bbname << ");";
break;
}
case Instruction::Br: {
const BranchInst* br = cast<BranchInst>(I);
Out << "BranchInst* " << iName << " = new BranchInst(" ;
if (br->getNumOperands() == 3 ) {
Out << opNames[0] << ", "
<< opNames[1] << ", "
<< opNames[2] << ", ";
} else if (br->getNumOperands() == 1) {
Out << opNames[0] << ", ";
} else {
error("Branch with 2 operands?");
}
Out << bbname << ");";
break;
}
case Instruction::Switch: {
const SwitchInst* sw = cast<SwitchInst>(I);
Out << "SwitchInst* " << iName << " = new SwitchInst("
<< opNames[0] << ", "
<< opNames[1] << ", "
<< sw->getNumCases() << ", " << bbname << ");";
nl(Out);
for (unsigned i = 2; i < sw->getNumOperands(); i += 2 ) {
Out << iName << "->addCase("
<< opNames[i] << ", "
<< opNames[i+1] << ");";
nl(Out);
}
break;
}
case Instruction::Invoke: {
const InvokeInst* inv = cast<InvokeInst>(I);
Out << "std::vector<Value*> " << iName << "_params;";
nl(Out);
for (unsigned i = 3; i < inv->getNumOperands(); ++i) {
Out << iName << "_params.push_back("
<< opNames[i] << ");";
nl(Out);
}
Out << "InvokeInst* " << iName << " = new InvokeInst("
<< opNames[0] << ", "
<< opNames[1] << ", "
<< opNames[2] << ", "
<< iName << "_params, \"";
printEscapedString(inv->getName());
Out << "\", " << bbname << ");";
nl(Out) << iName << "->setCallingConv(";
printCallingConv(inv->getCallingConv());
Out << ");";
break;
}
case Instruction::Unwind: {
Out << "UnwindInst* " << iName << " = new UnwindInst("
<< bbname << ");";
break;
}
case Instruction::Unreachable:{
Out << "UnreachableInst* " << iName << " = new UnreachableInst("
<< bbname << ");";
break;
}
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv:
case Instruction::URem:
case Instruction::SRem:
case Instruction::FRem:
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
case Instruction::Shl:
case Instruction::Shr:{
Out << "BinaryOperator* " << iName << " = BinaryOperator::create(";
switch (I->getOpcode()) {
case Instruction::Add: Out << "Instruction::Add"; break;
case Instruction::Sub: Out << "Instruction::Sub"; break;
case Instruction::Mul: Out << "Instruction::Mul"; break;
case Instruction::UDiv:Out << "Instruction::UDiv"; break;
case Instruction::SDiv:Out << "Instruction::SDiv"; break;
case Instruction::FDiv:Out << "Instruction::FDiv"; break;
case Instruction::URem:Out << "Instruction::URem"; break;
case Instruction::SRem:Out << "Instruction::SRem"; break;
case Instruction::FRem:Out << "Instruction::FRem"; break;
case Instruction::And: Out << "Instruction::And"; break;
case Instruction::Or: Out << "Instruction::Or"; break;
case Instruction::Xor: Out << "Instruction::Xor"; break;
case Instruction::Shl: Out << "Instruction::Shl"; break;
case Instruction::Shr: Out << "Instruction::Shr"; break;
default: Out << "Instruction::BadOpCode"; break;
}
Out << ", " << opNames[0] << ", " << opNames[1] << ", \"";
printEscapedString(I->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::SetEQ:
case Instruction::SetNE:
case Instruction::SetLE:
case Instruction::SetGE:
case Instruction::SetLT:
case Instruction::SetGT: {
Out << "SetCondInst* " << iName << " = new SetCondInst(";
switch (I->getOpcode()) {
case Instruction::SetEQ: Out << "Instruction::SetEQ"; break;
case Instruction::SetNE: Out << "Instruction::SetNE"; break;
case Instruction::SetLE: Out << "Instruction::SetLE"; break;
case Instruction::SetGE: Out << "Instruction::SetGE"; break;
case Instruction::SetLT: Out << "Instruction::SetLT"; break;
case Instruction::SetGT: Out << "Instruction::SetGT"; break;
default: Out << "Instruction::BadOpCode"; break;
}
Out << ", " << opNames[0] << ", " << opNames[1] << ", \"";
printEscapedString(I->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::Malloc: {
const MallocInst* mallocI = cast<MallocInst>(I);
Out << "MallocInst* " << iName << " = new MallocInst("
<< getCppName(mallocI->getAllocatedType()) << ", ";
if (mallocI->isArrayAllocation())
Out << opNames[0] << ", " ;
Out << "\"";
printEscapedString(mallocI->getName());
Out << "\", " << bbname << ");";
if (mallocI->getAlignment())
nl(Out) << iName << "->setAlignment("
<< mallocI->getAlignment() << ");";
break;
}
case Instruction::Free: {
Out << "FreeInst* " << iName << " = new FreeInst("
<< getCppName(I->getOperand(0)) << ", " << bbname << ");";
break;
}
case Instruction::Alloca: {
const AllocaInst* allocaI = cast<AllocaInst>(I);
Out << "AllocaInst* " << iName << " = new AllocaInst("
<< getCppName(allocaI->getAllocatedType()) << ", ";
if (allocaI->isArrayAllocation())
Out << opNames[0] << ", ";
Out << "\"";
printEscapedString(allocaI->getName());
Out << "\", " << bbname << ");";
if (allocaI->getAlignment())
nl(Out) << iName << "->setAlignment("
<< allocaI->getAlignment() << ");";
break;
}
case Instruction::Load:{
const LoadInst* load = cast<LoadInst>(I);
Out << "LoadInst* " << iName << " = new LoadInst("
<< opNames[0] << ", \"";
printEscapedString(load->getName());
Out << "\", " << (load->isVolatile() ? "true" : "false" )
<< ", " << bbname << ");";
break;
}
case Instruction::Store: {
const StoreInst* store = cast<StoreInst>(I);
Out << "StoreInst* " << iName << " = new StoreInst("
<< opNames[0] << ", "
<< opNames[1] << ", "
<< (store->isVolatile() ? "true" : "false")
<< ", " << bbname << ");";
break;
}
case Instruction::GetElementPtr: {
const GetElementPtrInst* gep = cast<GetElementPtrInst>(I);
if (gep->getNumOperands() <= 2) {
Out << "GetElementPtrInst* " << iName << " = new GetElementPtrInst("
<< opNames[0];
if (gep->getNumOperands() == 2)
Out << ", " << opNames[1];
} else {
Out << "std::vector<Value*> " << iName << "_indices;";
nl(Out);
for (unsigned i = 1; i < gep->getNumOperands(); ++i ) {
Out << iName << "_indices.push_back("
<< opNames[i] << ");";
nl(Out);
}
Out << "Instruction* " << iName << " = new GetElementPtrInst("
<< opNames[0] << ", " << iName << "_indices";
}
Out << ", \"";
printEscapedString(gep->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::PHI: {
const PHINode* phi = cast<PHINode>(I);
Out << "PHINode* " << iName << " = new PHINode("
<< getCppName(phi->getType()) << ", \"";
printEscapedString(phi->getName());
Out << "\", " << bbname << ");";
nl(Out) << iName << "->reserveOperandSpace("
<< phi->getNumIncomingValues()
<< ");";
nl(Out);
for (unsigned i = 0; i < phi->getNumOperands(); i+=2) {
Out << iName << "->addIncoming("
<< opNames[i] << ", " << opNames[i+1] << ");";
nl(Out);
}
break;
}
case Instruction::Cast: {
const CastInst* cst = cast<CastInst>(I);
Out << "CastInst* " << iName << " = new CastInst("
<< opNames[0] << ", "
<< getCppName(cst->getType()) << ", \"";
printEscapedString(cst->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::Call:{
const CallInst* call = cast<CallInst>(I);
if (InlineAsm* ila = dyn_cast<InlineAsm>(call->getOperand(0))) {
Out << "InlineAsm* " << getCppName(ila) << " = InlineAsm::get("
<< getCppName(ila->getFunctionType()) << ", \""
<< ila->getAsmString() << "\", \""
<< ila->getConstraintString() << "\","
<< (ila->hasSideEffects() ? "true" : "false") << ");";
nl(Out);
}
if (call->getNumOperands() > 3) {
Out << "std::vector<Value*> " << iName << "_params;";
nl(Out);
for (unsigned i = 1; i < call->getNumOperands(); ++i) {
Out << iName << "_params.push_back(" << opNames[i] << ");";
nl(Out);
}
Out << "CallInst* " << iName << " = new CallInst("
<< opNames[0] << ", " << iName << "_params, \"";
} else if (call->getNumOperands() == 3) {
Out << "CallInst* " << iName << " = new CallInst("
<< opNames[0] << ", " << opNames[1] << ", " << opNames[2] << ", \"";
} else if (call->getNumOperands() == 2) {
Out << "CallInst* " << iName << " = new CallInst("
<< opNames[0] << ", " << opNames[1] << ", \"";
} else {
Out << "CallInst* " << iName << " = new CallInst(" << opNames[0]
<< ", \"";
}
printEscapedString(call->getName());
Out << "\", " << bbname << ");";
nl(Out) << iName << "->setCallingConv(";
printCallingConv(call->getCallingConv());
Out << ");";
nl(Out) << iName << "->setTailCall("
<< (call->isTailCall() ? "true":"false");
Out << ");";
break;
}
case Instruction::Select: {
const SelectInst* sel = cast<SelectInst>(I);
Out << "SelectInst* " << getCppName(sel) << " = new SelectInst(";
Out << opNames[0] << ", " << opNames[1] << ", " << opNames[2] << ", \"";
printEscapedString(sel->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::UserOp1:
/// FALL THROUGH
case Instruction::UserOp2: {
/// FIXME: What should be done here?
break;
}
case Instruction::VAArg: {
const VAArgInst* va = cast<VAArgInst>(I);
Out << "VAArgInst* " << getCppName(va) << " = new VAArgInst("
<< opNames[0] << ", " << getCppName(va->getType()) << ", \"";
printEscapedString(va->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::ExtractElement: {
const ExtractElementInst* eei = cast<ExtractElementInst>(I);
Out << "ExtractElementInst* " << getCppName(eei)
<< " = new ExtractElementInst(" << opNames[0]
<< ", " << opNames[1] << ", \"";
printEscapedString(eei->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::InsertElement: {
const InsertElementInst* iei = cast<InsertElementInst>(I);
Out << "InsertElementInst* " << getCppName(iei)
<< " = new InsertElementInst(" << opNames[0]
<< ", " << opNames[1] << ", " << opNames[2] << ", \"";
printEscapedString(iei->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::ShuffleVector: {
const ShuffleVectorInst* svi = cast<ShuffleVectorInst>(I);
Out << "ShuffleVectorInst* " << getCppName(svi)
<< " = new ShuffleVectorInst(" << opNames[0]
<< ", " << opNames[1] << ", " << opNames[2] << ", \"";
printEscapedString(svi->getName());
Out << "\", " << bbname << ");";
break;
}
}
DefinedValues.insert(I);
nl(Out);
delete [] opNames;
}
// Print out the types, constants and declarations needed by one function
void CppWriter::printFunctionUses(const Function* F) {
nl(Out) << "// Type Definitions"; nl(Out);
if (!is_inline) {
// Print the function's return type
printType(F->getReturnType());
// Print the function's function type
printType(F->getFunctionType());
// Print the types of each of the function's arguments
for(Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
AI != AE; ++AI) {
printType(AI->getType());
}
}
// Print type definitions for every type referenced by an instruction and
// make a note of any global values or constants that are referenced
std::vector<GlobalValue*> gvs;
std::vector<Constant*> consts;
for (Function::const_iterator BB = F->begin(), BE = F->end(); BB != BE; ++BB){
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
I != E; ++I) {
// Print the type of the instruction itself
printType(I->getType());
// Print the type of each of the instruction's operands
for (unsigned i = 0; i < I->getNumOperands(); ++i) {
Value* operand = I->getOperand(i);
printType(operand->getType());
if (GlobalValue* GV = dyn_cast<GlobalValue>(operand))
gvs.push_back(GV);
else if (Constant* C = dyn_cast<Constant>(operand))
consts.push_back(C);
}
}
}
// Print the function declarations for any functions encountered
nl(Out) << "// Function Declarations"; nl(Out);
for (std::vector<GlobalValue*>::iterator I = gvs.begin(), E = gvs.end();
I != E; ++I) {
if (Function* Fun = dyn_cast<Function>(*I)) {
if (!is_inline || Fun != F)
printFunctionHead(Fun);
}
}
// Print the global variable declarations for any variables encountered
nl(Out) << "// Global Variable Declarations"; nl(Out);
for (std::vector<GlobalValue*>::iterator I = gvs.begin(), E = gvs.end();
I != E; ++I) {
if (GlobalVariable* F = dyn_cast<GlobalVariable>(*I))
printVariableHead(F);
}
// Print the constants found
nl(Out) << "// Constant Definitions"; nl(Out);
for (std::vector<Constant*>::iterator I = consts.begin(), E = consts.end();
I != E; ++I) {
printConstant(*I);
}
// Process the global variables definitions now that all the constants have
// been emitted. These definitions just couple the gvars with their constant
// initializers.
nl(Out) << "// Global Variable Definitions"; nl(Out);
for (std::vector<GlobalValue*>::iterator I = gvs.begin(), E = gvs.end();
I != E; ++I) {
if (GlobalVariable* GV = dyn_cast<GlobalVariable>(*I))
printVariableBody(GV);
}
}
void CppWriter::printFunctionHead(const Function* F) {
nl(Out) << "Function* " << getCppName(F);
if (is_inline) {
Out << " = mod->getFunction(\"";
printEscapedString(F->getName());
Out << "\", " << getCppName(F->getFunctionType()) << ");";
nl(Out) << "if (!" << getCppName(F) << ") {";
nl(Out) << getCppName(F);
}
Out<< " = new Function(";
nl(Out,1) << "/*Type=*/" << getCppName(F->getFunctionType()) << ",";
nl(Out) << "/*Linkage=*/";
printLinkageType(F->getLinkage());
Out << ",";
nl(Out) << "/*Name=*/\"";
printEscapedString(F->getName());
Out << "\", mod); " << (F->isExternal()? "// (external, no body)" : "");
nl(Out,-1);
printCppName(F);
Out << "->setCallingConv(";
printCallingConv(F->getCallingConv());
Out << ");";
nl(Out);
if (F->hasSection()) {
printCppName(F);
Out << "->setSection(\"" << F->getSection() << "\");";
nl(Out);
}
if (F->getAlignment()) {
printCppName(F);
Out << "->setAlignment(" << F->getAlignment() << ");";
nl(Out);
}
if (is_inline) {
Out << "}";
nl(Out);
}
}
void CppWriter::printFunctionBody(const Function *F) {
if (F->isExternal())
return; // external functions have no bodies.
// Clear the DefinedValues and ForwardRefs maps because we can't have
// cross-function forward refs
ForwardRefs.clear();
DefinedValues.clear();
// Create all the argument values
if (!is_inline) {
if (!F->arg_empty()) {
Out << "Function::arg_iterator args = " << getCppName(F)
<< "->arg_begin();";
nl(Out);
}
for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
AI != AE; ++AI) {
Out << "Value* " << getCppName(AI) << " = args++;";
nl(Out);
if (AI->hasName()) {
Out << getCppName(AI) << "->setName(\"" << AI->getName() << "\");";
nl(Out);
}
}
}
// Create all the basic blocks
nl(Out);
for (Function::const_iterator BI = F->begin(), BE = F->end();
BI != BE; ++BI) {
std::string bbname(getCppName(BI));
Out << "BasicBlock* " << bbname << " = new BasicBlock(\"";
if (BI->hasName())
printEscapedString(BI->getName());
Out << "\"," << getCppName(BI->getParent()) << ",0);";
nl(Out);
}
// Output all of its basic blocks... for the function
for (Function::const_iterator BI = F->begin(), BE = F->end();
BI != BE; ++BI) {
std::string bbname(getCppName(BI));
nl(Out) << "// Block " << BI->getName() << " (" << bbname << ")";
nl(Out);
// Output all of the instructions in the basic block...
for (BasicBlock::const_iterator I = BI->begin(), E = BI->end();
I != E; ++I) {
printInstruction(I,bbname);
}
}
// Loop over the ForwardRefs and resolve them now that all instructions
// are generated.
if (!ForwardRefs.empty()) {
nl(Out) << "// Resolve Forward References";
nl(Out);
}
while (!ForwardRefs.empty()) {
ForwardRefMap::iterator I = ForwardRefs.begin();
Out << I->second << "->replaceAllUsesWith("
<< getCppName(I->first) << "); delete " << I->second << ";";
nl(Out);
ForwardRefs.erase(I);
}
}
void CppWriter::printInline(const std::string& fname, const std::string& func) {
const Function* F = TheModule->getNamedFunction(func);
if (!F) {
error(std::string("Function '") + func + "' not found in input module");
return;
}
if (F->isExternal()) {
error(std::string("Function '") + func + "' is external!");
return;
}
nl(Out) << "BasicBlock* " << fname << "(Module* mod, Function *"
<< getCppName(F);
unsigned arg_count = 1;
for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
AI != AE; ++AI) {
Out << ", Value* arg_" << arg_count;
}
Out << ") {";
nl(Out);
is_inline = true;
printFunctionUses(F);
printFunctionBody(F);
is_inline = false;
Out << "return " << getCppName(F->begin()) << ";";
nl(Out) << "}";
nl(Out);
}
void CppWriter::printModuleBody() {
// Print out all the type definitions
nl(Out) << "// Type Definitions"; nl(Out);
printTypes(TheModule);
// Functions can call each other and global variables can reference them so
// define all the functions first before emitting their function bodies.
nl(Out) << "// Function Declarations"; nl(Out);
for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
I != E; ++I)
printFunctionHead(I);
// Process the global variables declarations. We can't initialze them until
// after the constants are printed so just print a header for each global
nl(Out) << "// Global Variable Declarations\n"; nl(Out);
for (Module::const_global_iterator I = TheModule->global_begin(),
E = TheModule->global_end(); I != E; ++I) {
printVariableHead(I);
}
// Print out all the constants definitions. Constants don't recurse except
// through GlobalValues. All GlobalValues have been declared at this point
// so we can proceed to generate the constants.
nl(Out) << "// Constant Definitions"; nl(Out);
printConstants(TheModule);
// Process the global variables definitions now that all the constants have
// been emitted. These definitions just couple the gvars with their constant
// initializers.
nl(Out) << "// Global Variable Definitions"; nl(Out);
for (Module::const_global_iterator I = TheModule->global_begin(),
E = TheModule->global_end(); I != E; ++I) {
printVariableBody(I);
}
// Finally, we can safely put out all of the function bodies.
nl(Out) << "// Function Definitions"; nl(Out);
for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
I != E; ++I) {
if (!I->isExternal()) {
nl(Out) << "// Function: " << I->getName() << " (" << getCppName(I)
<< ")";
nl(Out) << "{";
nl(Out,1);
printFunctionBody(I);
nl(Out,-1) << "}";
nl(Out);
}
}
}
void CppWriter::printProgram(
const std::string& fname,
const std::string& mName
) {
Out << "#include <llvm/Module.h>\n";
Out << "#include <llvm/DerivedTypes.h>\n";
Out << "#include <llvm/Constants.h>\n";
Out << "#include <llvm/GlobalVariable.h>\n";
Out << "#include <llvm/Function.h>\n";
Out << "#include <llvm/CallingConv.h>\n";
Out << "#include <llvm/BasicBlock.h>\n";
Out << "#include <llvm/Instructions.h>\n";
Out << "#include <llvm/InlineAsm.h>\n";
Out << "#include <llvm/Support/MathExtras.h>\n";
Out << "#include <llvm/Pass.h>\n";
Out << "#include <llvm/PassManager.h>\n";
Out << "#include <llvm/Analysis/Verifier.h>\n";
Out << "#include <llvm/Assembly/PrintModulePass.h>\n";
Out << "#include <algorithm>\n";
Out << "#include <iostream>\n\n";
Out << "using namespace llvm;\n\n";
Out << "Module* " << fname << "();\n\n";
Out << "int main(int argc, char**argv) {\n";
Out << " Module* Mod = makeLLVMModule();\n";
Out << " verifyModule(*Mod, PrintMessageAction);\n";
Out << " std::cerr.flush();\n";
Out << " std::cout.flush();\n";
Out << " PassManager PM;\n";
Out << " PM.add(new PrintModulePass(&std::cout));\n";
Out << " PM.run(*Mod);\n";
Out << " return 0;\n";
Out << "}\n\n";
printModule(fname,mName);
}
void CppWriter::printModule(
const std::string& fname,
const std::string& mName
) {
nl(Out) << "Module* " << fname << "() {";
nl(Out,1) << "// Module Construction";
nl(Out) << "Module* mod = new Module(\"" << mName << "\");";
nl(Out) << "mod->setEndianness(";
switch (TheModule->getEndianness()) {
case Module::LittleEndian: Out << "Module::LittleEndian);"; break;
case Module::BigEndian: Out << "Module::BigEndian);"; break;
case Module::AnyEndianness:Out << "Module::AnyEndianness);"; break;
}
nl(Out) << "mod->setPointerSize(";
switch (TheModule->getPointerSize()) {
case Module::Pointer32: Out << "Module::Pointer32);"; break;
case Module::Pointer64: Out << "Module::Pointer64);"; break;
case Module::AnyPointerSize: Out << "Module::AnyPointerSize);"; break;
}
nl(Out);
if (!TheModule->getTargetTriple().empty()) {
Out << "mod->setTargetTriple(\"" << TheModule->getTargetTriple()
<< "\");";
nl(Out);
}
if (!TheModule->getModuleInlineAsm().empty()) {
Out << "mod->setModuleInlineAsm(\"";
printEscapedString(TheModule->getModuleInlineAsm());
Out << "\");";
nl(Out);
}
// Loop over the dependent libraries and emit them.
Module::lib_iterator LI = TheModule->lib_begin();
Module::lib_iterator LE = TheModule->lib_end();
while (LI != LE) {
Out << "mod->addLibrary(\"" << *LI << "\");";
nl(Out);
++LI;
}
printModuleBody();
nl(Out) << "return mod;";
nl(Out,-1) << "}";
nl(Out);
}
void CppWriter::printContents(
const std::string& fname, // Name of generated function
const std::string& mName // Name of module generated module
) {
Out << "\nModule* " << fname << "(Module *mod) {\n";
Out << "\nmod->setModuleIdentifier(\"" << mName << "\");\n";
printModuleBody();
Out << "\nreturn mod;\n";
Out << "\n}\n";
}
void CppWriter::printFunction(
const std::string& fname, // Name of generated function
const std::string& funcName // Name of function to generate
) {
const Function* F = TheModule->getNamedFunction(funcName);
if (!F) {
error(std::string("Function '") + funcName + "' not found in input module");
return;
}
Out << "\nFunction* " << fname << "(Module *mod) {\n";
printFunctionUses(F);
printFunctionHead(F);
printFunctionBody(F);
Out << "return " << getCppName(F) << ";\n";
Out << "}\n";
}
void CppWriter::printVariable(
const std::string& fname, /// Name of generated function
const std::string& varName // Name of variable to generate
) {
const GlobalVariable* GV = TheModule->getNamedGlobal(varName);
if (!GV) {
error(std::string("Variable '") + varName + "' not found in input module");
return;
}
Out << "\nGlobalVariable* " << fname << "(Module *mod) {\n";
printVariableUses(GV);
printVariableHead(GV);
printVariableBody(GV);
Out << "return " << getCppName(GV) << ";\n";
Out << "}\n";
}
void CppWriter::printType(
const std::string& fname, /// Name of generated function
const std::string& typeName // Name of type to generate
) {
const Type* Ty = TheModule->getTypeByName(typeName);
if (!Ty) {
error(std::string("Type '") + typeName + "' not found in input module");
return;
}
Out << "\nType* " << fname << "(Module *mod) {\n";
printType(Ty);
Out << "return " << getCppName(Ty) << ";\n";
Out << "}\n";
}
} // end anonymous llvm
namespace llvm {
void WriteModuleToCppFile(Module* mod, std::ostream& o) {
// Initialize a CppWriter for us to use
CppWriter W(o, mod);
// Emit a header
o << "// Generated by llvm2cpp - DO NOT MODIFY!\n\n";
// Get the name of the function we're supposed to generate
std::string fname = FuncName.getValue();
// Get the name of the thing we are to generate
std::string tgtname = NameToGenerate.getValue();
if (GenerationType == GenModule ||
GenerationType == GenContents ||
GenerationType == GenProgram) {
if (tgtname == "!bad!") {
if (mod->getModuleIdentifier() == "-")
tgtname = "<stdin>";
else
tgtname = mod->getModuleIdentifier();
}
} else if (tgtname == "!bad!") {
W.error("You must use the -for option with -gen-{function,variable,type}");
}
switch (WhatToGenerate(GenerationType)) {
case GenProgram:
if (fname.empty())
fname = "makeLLVMModule";
W.printProgram(fname,tgtname);
break;
case GenModule:
if (fname.empty())
fname = "makeLLVMModule";
W.printModule(fname,tgtname);
break;
case GenContents:
if (fname.empty())
fname = "makeLLVMModuleContents";
W.printContents(fname,tgtname);
break;
case GenFunction:
if (fname.empty())
fname = "makeLLVMFunction";
W.printFunction(fname,tgtname);
break;
case GenInline:
if (fname.empty())
fname = "makeLLVMInline";
W.printInline(fname,tgtname);
break;
case GenVariable:
if (fname.empty())
fname = "makeLLVMVariable";
W.printVariable(fname,tgtname);
break;
case GenType:
if (fname.empty())
fname = "makeLLVMType";
W.printType(fname,tgtname);
break;
default:
W.error("Invalid generation option");
}
}
}