llvm-6502/tools/llvm2cpp/CppWriter.cpp
Duncan Sands dc024674ff Fix PR1146: parameter attributes are longer part of
the function type, instead they belong to functions
and function calls.  This is an updated and slightly
corrected version of Reid Spencer's original patch.
The only known problem is that auto-upgrading of
bitcode files doesn't seem to work properly (see
test/Bitcode/AutoUpgradeIntrinsics.ll).  Hopefully
a bitcode guru (who might that be? :) ) will fix it.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44359 91177308-0d34-0410-b5e6-96231b3b80d8
2007-11-27 13:23:08 +00:00

1955 lines
68 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/ParameterAttributes.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 ParamAttrsList* 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 ParamAttrsList* PAL, const std::string &name) {
Out << "ParamAttrsList *" << name << "_PAL = 0;";
nl(Out);
if (PAL) {
Out << '{'; in(); nl(Out);
Out << "ParamAttrsVector Attrs;"; nl(Out);
Out << "ParamAttrsWithIndex PAWI;"; nl(Out);
for (unsigned i = 0; i < PAL->size(); ++i) {
uint16_t index = PAL->getParamIndex(i);
uint16_t attrs = PAL->getParamAttrs(index);
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";
Out << ";";
nl(Out);
Out << "Attrs.push_back(PAWI);";
nl(Out);
}
Out << name << "_PAL = ParamAttrsList::get(Attrs);";
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" : "") << ");";
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:
Out << "getFCmp(FCmpInst::FCMP_";
switch (CE->getPredicate()) {
case FCmpInst::FCMP_FALSE: Out << "FALSE"; break;
case FCmpInst::FCMP_ORD: Out << "ORD"; break;
case FCmpInst::FCMP_UNO: Out << "UNO"; break;
case FCmpInst::FCMP_OEQ: Out << "OEQ"; break;
case FCmpInst::FCMP_UEQ: Out << "UEQ"; break;
case FCmpInst::FCMP_ONE: Out << "ONE"; break;
case FCmpInst::FCMP_UNE: Out << "UNE"; break;
case FCmpInst::FCMP_OLT: Out << "OLT"; break;
case FCmpInst::FCMP_ULT: Out << "ULT"; break;
case FCmpInst::FCMP_OGT: Out << "OGT"; break;
case FCmpInst::FCMP_UGT: Out << "UGT"; break;
case FCmpInst::FCMP_OLE: Out << "OLE"; break;
case FCmpInst::FCMP_ULE: Out << "ULE"; break;
case FCmpInst::FCMP_OGE: Out << "OGE"; break;
case FCmpInst::FCMP_UGE: Out << "UGE"; break;
case FCmpInst::FCMP_TRUE: Out << "TRUE"; break;
default: error("Invalid FCmp Predicate");
}
break;
case Instruction::Shl: Out << "getShl("; break;
case Instruction::LShr: Out << "getLShr("; break;
case Instruction::AShr: Out << "getAShr("; 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 (GV->getVisibility() != GlobalValue::DefaultVisibility) {
printCppName(GV);
Out << "->setVisibility(";
printVisibilityType(GV->getVisibility());
Out << ");";
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 << "new ReturnInst("
<< (ret->getReturnValue() ? opNames[0] + ", " : "") << bbname << ");";
break;
}
case Instruction::Br: {
const BranchInst* br = cast<BranchInst>(I);
Out << "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.begin(), " << iName << "_params.end(), \"";
printEscapedString(inv->getName());
Out << "\", " << bbname << ");";
nl(Out) << iName << "->setCallingConv(";
printCallingConv(inv->getCallingConv());
Out << ");";
printParamAttrs(inv->getParamAttrs(), iName);
Out << iName << "->setParamAttrs(" << iName << "_PAL);";
nl(Out);
break;
}
case Instruction::Unwind: {
Out << "new UnwindInst("
<< bbname << ");";
break;
}
case Instruction::Unreachable:{
Out << "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::LShr:
case Instruction::AShr:{
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::LShr:Out << "Instruction::LShr"; break;
case Instruction::AShr:Out << "Instruction::AShr"; break;
default: Out << "Instruction::BadOpCode"; break;
}
Out << ", " << opNames[0] << ", " << opNames[1] << ", \"";
printEscapedString(I->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::FCmp: {
Out << "FCmpInst* " << iName << " = new FCmpInst(";
switch (cast<FCmpInst>(I)->getPredicate()) {
case FCmpInst::FCMP_FALSE: Out << "FCmpInst::FCMP_FALSE"; break;
case FCmpInst::FCMP_OEQ : Out << "FCmpInst::FCMP_OEQ"; break;
case FCmpInst::FCMP_OGT : Out << "FCmpInst::FCMP_OGT"; break;
case FCmpInst::FCMP_OGE : Out << "FCmpInst::FCMP_OGE"; break;
case FCmpInst::FCMP_OLT : Out << "FCmpInst::FCMP_OLT"; break;
case FCmpInst::FCMP_OLE : Out << "FCmpInst::FCMP_OLE"; break;
case FCmpInst::FCMP_ONE : Out << "FCmpInst::FCMP_ONE"; break;
case FCmpInst::FCMP_ORD : Out << "FCmpInst::FCMP_ORD"; break;
case FCmpInst::FCMP_UNO : Out << "FCmpInst::FCMP_UNO"; break;
case FCmpInst::FCMP_UEQ : Out << "FCmpInst::FCMP_UEQ"; break;
case FCmpInst::FCMP_UGT : Out << "FCmpInst::FCMP_UGT"; break;
case FCmpInst::FCMP_UGE : Out << "FCmpInst::FCMP_UGE"; break;
case FCmpInst::FCMP_ULT : Out << "FCmpInst::FCMP_ULT"; break;
case FCmpInst::FCMP_ULE : Out << "FCmpInst::FCMP_ULE"; break;
case FCmpInst::FCMP_UNE : Out << "FCmpInst::FCMP_UNE"; break;
case FCmpInst::FCMP_TRUE : Out << "FCmpInst::FCMP_TRUE"; break;
default: Out << "FCmpInst::BAD_ICMP_PREDICATE"; break;
}
Out << ", " << opNames[0] << ", " << opNames[1] << ", \"";
printEscapedString(I->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::ICmp: {
Out << "ICmpInst* " << iName << " = new ICmpInst(";
switch (cast<ICmpInst>(I)->getPredicate()) {
case ICmpInst::ICMP_EQ: Out << "ICmpInst::ICMP_EQ"; break;
case ICmpInst::ICMP_NE: Out << "ICmpInst::ICMP_NE"; break;
case ICmpInst::ICMP_ULE: Out << "ICmpInst::ICMP_ULE"; break;
case ICmpInst::ICMP_SLE: Out << "ICmpInst::ICMP_SLE"; break;
case ICmpInst::ICMP_UGE: Out << "ICmpInst::ICMP_UGE"; break;
case ICmpInst::ICMP_SGE: Out << "ICmpInst::ICMP_SGE"; break;
case ICmpInst::ICMP_ULT: Out << "ICmpInst::ICMP_ULT"; break;
case ICmpInst::ICMP_SLT: Out << "ICmpInst::ICMP_SLT"; break;
case ICmpInst::ICMP_UGT: Out << "ICmpInst::ICMP_UGT"; break;
case ICmpInst::ICMP_SGT: Out << "ICmpInst::ICMP_SGT"; break;
default: Out << "ICmpInst::BAD_ICMP_PREDICATE"; 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.begin(), "
<< iName << "_indices.end()";
}
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::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast: {
const CastInst* cst = cast<CastInst>(I);
Out << "CastInst* " << iName << " = new ";
switch (I->getOpcode()) {
case Instruction::Trunc: Out << "TruncInst"; break;
case Instruction::ZExt: Out << "ZExtInst"; break;
case Instruction::SExt: Out << "SExtInst"; break;
case Instruction::FPTrunc: Out << "FPTruncInst"; break;
case Instruction::FPExt: Out << "FPExtInst"; break;
case Instruction::FPToUI: Out << "FPToUIInst"; break;
case Instruction::FPToSI: Out << "FPToSIInst"; break;
case Instruction::UIToFP: Out << "UIToFPInst"; break;
case Instruction::SIToFP: Out << "SIToFPInst"; break;
case Instruction::PtrToInt: Out << "PtrToIntInst"; break;
case Instruction::IntToPtr: Out << "IntToPtrInst"; break;
case Instruction::BitCast: Out << "BitCastInst"; break;
default: assert(!"Unreachable"); break;
}
Out << "(" << 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() > 2) {
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.begin(), "
<< iName << "_params.end(), \"";
} 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 << ");";
printParamAttrs(call->getParamAttrs(), iName);
Out << iName << "->setParamAttrs(" << iName << "_PAL);";
nl(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
SmallPtrSet<GlobalValue*,64> gvs;
SmallPtrSet<Constant*,64> 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 the operand references a GVal or Constant, make a note of it
if (GlobalValue* GV = dyn_cast<GlobalValue>(operand)) {
gvs.insert(GV);
if (GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
if (GVar->hasInitializer())
consts.insert(GVar->getInitializer());
} else if (Constant* C = dyn_cast<Constant>(operand))
consts.insert(C);
}
}
}
// Print the function declarations for any functions encountered
nl(Out) << "// Function Declarations"; nl(Out);
for (SmallPtrSet<GlobalValue*,64>::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 (SmallPtrSet<GlobalValue*,64>::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 (SmallPtrSet<Constant*,64>::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 (SmallPtrSet<GlobalValue*,64>::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->isDeclaration()? "// (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 (F->getVisibility() != GlobalValue::DefaultVisibility) {
printCppName(F);
Out << "->setVisibility(";
printVisibilityType(F->getVisibility());
Out << ");";
nl(Out);
}
if (is_inline) {
Out << "}";
nl(Out);
}
printParamAttrs(F->getParamAttrs(), getCppName(F));
printCppName(F);
Out << "->setParamAttrs(" << getCppName(F) << "_PAL);";
nl(Out);
}
void CppWriter::printFunctionBody(const Function *F) {
if (F->isDeclaration())
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->getFunction(func);
if (!F) {
error(std::string("Function '") + func + "' not found in input module");
return;
}
if (F->isDeclaration()) {
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->isDeclaration()) {
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/ParameterAttributes.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 = " << fname << "();\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(&llvm::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 << "\");";
if (!TheModule->getTargetTriple().empty()) {
nl(Out) << "mod->setDataLayout(\"" << TheModule->getDataLayout() << "\");";
}
if (!TheModule->getTargetTriple().empty()) {
nl(Out) << "mod->setTargetTriple(\"" << TheModule->getTargetTriple()
<< "\");";
}
if (!TheModule->getModuleInlineAsm().empty()) {
nl(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->getFunction(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::printFunctions() {
const Module::FunctionListType &funcs = TheModule->getFunctionList();
Module::const_iterator I = funcs.begin();
Module::const_iterator IE = funcs.end();
for (; I != IE; ++I) {
const Function &func = *I;
if (!func.isDeclaration()) {
std::string name("define_");
name += func.getName();
printFunction(name, func.getName());
}
}
}
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 ||
GenerationType == GenFunctions) {
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 GenFunctions:
W.printFunctions();
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");
}
}
}