mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-22 10:33:23 +00:00
e0d133f448
1. Get rid of old AsmWriter cruft that's not needed. 2. Implement several instructions. Enough to get by globalvars.ll and alignment.ll in the Feature test suite. 3. Handle constants properly (don't repeat definitions). 4. Make the output compatible with llvm-dis for diff purposes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28541 91177308-0d34-0410-b5e6-96231b3b80d8
1121 lines
40 KiB
C++
1121 lines
40 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 <algorithm>
|
|
#include <iostream>
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
typedef std::vector<const Type*> TypeList;
|
|
typedef std::map<const Type*,std::string> TypeMap;
|
|
typedef std::map<const Value*,std::string> ValueMap;
|
|
|
|
class CppWriter {
|
|
std::ostream &Out;
|
|
const Module *TheModule;
|
|
unsigned long uniqueNum;
|
|
TypeMap TypeNames;
|
|
ValueMap ValueNames;
|
|
TypeMap UnresolvedTypes;
|
|
TypeList TypeStack;
|
|
|
|
public:
|
|
inline CppWriter(std::ostream &o, const Module *M)
|
|
: Out(o), TheModule(M), uniqueNum(0), TypeNames(),
|
|
ValueNames(), UnresolvedTypes(), TypeStack() { }
|
|
|
|
const Module* getModule() { return TheModule; }
|
|
|
|
void printModule(const Module *M);
|
|
|
|
private:
|
|
void printTypes(const Module* M);
|
|
void printConstants(const Module* M);
|
|
void printConstant(const Constant *CPV);
|
|
void printGlobal(const GlobalVariable *GV);
|
|
void printFunction(const Function *F);
|
|
void printInstruction(const Instruction *I, const std::string& bbname);
|
|
void printSymbolTable(const SymbolTable &ST);
|
|
void printLinkageType(GlobalValue::LinkageTypes LT);
|
|
void printCallingConv(unsigned cc);
|
|
|
|
std::string getCppName(const Type* val);
|
|
std::string getCppName(const Value* val);
|
|
inline void printCppName(const Value* val);
|
|
inline void printCppName(const Type* val);
|
|
bool isOnStack(const Type*) const;
|
|
inline void printTypeDef(const Type* Ty);
|
|
bool printTypeDefInternal(const Type* Ty);
|
|
void printEscapedString(const std::string& str);
|
|
};
|
|
|
|
// 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 << '\\'
|
|
<< (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 Value* val) {
|
|
std::string name;
|
|
ValueMap::iterator I = ValueNames.find(val);
|
|
if (I != ValueNames.end()) {
|
|
name = I->second;
|
|
} else {
|
|
const char* prefix;
|
|
switch (val->getType()->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;
|
|
default: prefix = "other_"; break;
|
|
}
|
|
name = ValueNames[val] = std::string(prefix) +
|
|
(val->hasName() ? val->getName() : utostr(uniqueNum++));
|
|
}
|
|
return name;
|
|
}
|
|
|
|
void
|
|
CppWriter::printCppName(const Value* val) {
|
|
printEscapedString(getCppName(val));
|
|
}
|
|
|
|
void
|
|
CppWriter::printCppName(const Type* Ty)
|
|
{
|
|
printEscapedString(getCppName(Ty));
|
|
}
|
|
|
|
// Gets the C++ name for a type. Returns true if we already saw the type,
|
|
// false otherwise.
|
|
//
|
|
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;
|
|
}
|
|
|
|
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:
|
|
assert(!"Can't get here");
|
|
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++);
|
|
|
|
// Save the name
|
|
return TypeNames[Ty] = name;
|
|
}
|
|
|
|
void CppWriter::printModule(const Module *M) {
|
|
Out << "\n// Module Construction\n";
|
|
Out << "Module* mod = new Module(\"";
|
|
if (M->getModuleIdentifier() == "-")
|
|
printEscapedString("<stdin>");
|
|
else
|
|
printEscapedString(M->getModuleIdentifier());
|
|
Out << "\");\n";
|
|
Out << "mod->setEndianness(";
|
|
switch (M->getEndianness()) {
|
|
case Module::LittleEndian: Out << "Module::LittleEndian);\n"; break;
|
|
case Module::BigEndian: Out << "Module::BigEndian);\n"; break;
|
|
case Module::AnyEndianness:Out << "Module::AnyEndianness);\n"; break;
|
|
}
|
|
Out << "mod->setPointerSize(";
|
|
switch (M->getPointerSize()) {
|
|
case Module::Pointer32: Out << "Module::Pointer32);\n"; break;
|
|
case Module::Pointer64: Out << "Module::Pointer64);\n"; break;
|
|
case Module::AnyPointerSize: Out << "Module::AnyPointerSize);\n"; break;
|
|
}
|
|
if (!M->getTargetTriple().empty())
|
|
Out << "mod->setTargetTriple(\"" << M->getTargetTriple() << "\");\n";
|
|
|
|
if (!M->getModuleInlineAsm().empty()) {
|
|
Out << "mod->setModuleInlineAsm(\"";
|
|
printEscapedString(M->getModuleInlineAsm());
|
|
Out << "\");\n";
|
|
}
|
|
|
|
// Loop over the dependent libraries and emit them.
|
|
Module::lib_iterator LI = M->lib_begin();
|
|
Module::lib_iterator LE = M->lib_end();
|
|
while (LI != LE) {
|
|
Out << "mod->addLibrary(\"" << *LI << "\");\n";
|
|
++LI;
|
|
}
|
|
|
|
// Print out all the type definitions
|
|
Out << "\n// Type Definitions\n";
|
|
printTypes(M);
|
|
|
|
// Print out all the constants declarations
|
|
Out << "\n// Constants Construction\n";
|
|
printConstants(M);
|
|
|
|
// Process the global variables
|
|
Out << "\n// Global Variable Construction\n";
|
|
for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
|
|
I != E; ++I) {
|
|
printGlobal(I);
|
|
}
|
|
|
|
// Output all of the functions.
|
|
Out << "\n// Function Construction\n";
|
|
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
|
|
printFunction(I);
|
|
}
|
|
|
|
void
|
|
CppWriter::printCallingConv(unsigned cc){
|
|
// Print the calling convention.
|
|
switch (cc) {
|
|
default:
|
|
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;
|
|
}
|
|
}
|
|
|
|
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::GhostLinkage:
|
|
Out << "GlobalValue::GhostLinkage"; break;
|
|
}
|
|
}
|
|
void CppWriter::printGlobal(const GlobalVariable *GV) {
|
|
Out << "\n";
|
|
Out << "GlobalVariable* ";
|
|
printCppName(GV);
|
|
Out << " = new GlobalVariable(\n";
|
|
Out << " /*Type=*/";
|
|
printCppName(GV->getType()->getElementType());
|
|
Out << ",\n";
|
|
Out << " /*isConstant=*/" << (GV->isConstant()?"true":"false")
|
|
<< ",\n /*Linkage=*/";
|
|
printLinkageType(GV->getLinkage());
|
|
Out << ",\n /*Initializer=*/";
|
|
if (GV->hasInitializer()) {
|
|
printCppName(GV->getInitializer());
|
|
} else {
|
|
Out << "0";
|
|
}
|
|
Out << ",\n /*Name=*/\"";
|
|
printEscapedString(GV->getName());
|
|
Out << "\",\n mod);\n";
|
|
|
|
if (GV->hasSection()) {
|
|
printCppName(GV);
|
|
Out << "->setSection(\"";
|
|
printEscapedString(GV->getSection());
|
|
Out << "\");\n";
|
|
}
|
|
if (GV->getAlignment()) {
|
|
printCppName(GV);
|
|
Out << "->setAlignment(" << utostr(GV->getAlignment()) << ");\n";
|
|
};
|
|
}
|
|
|
|
bool
|
|
CppWriter::isOnStack(const Type* Ty) const {
|
|
TypeList::const_iterator TI =
|
|
std::find(TypeStack.begin(),TypeStack.end(),Ty);
|
|
return TI != TypeStack.end();
|
|
}
|
|
|
|
// 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::printTypeDef(const Type* Ty) {
|
|
assert(TypeStack.empty());
|
|
TypeStack.clear();
|
|
printTypeDefInternal(Ty);
|
|
assert(TypeStack.empty());
|
|
// 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 preview 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 << ");\n";
|
|
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());\n\n";
|
|
UnresolvedTypes.erase(I);
|
|
}
|
|
}
|
|
|
|
bool
|
|
CppWriter::printTypeDefInternal(const Type* Ty) {
|
|
// We don't print definitions for primitive types
|
|
if (Ty->isPrimitiveType())
|
|
return false;
|
|
|
|
// Determine if the name is in the name list before we modify that list.
|
|
TypeMap::const_iterator TNI = TypeNames.find(Ty);
|
|
|
|
// 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 issues, it must not be re-issued. Consequently we have to
|
|
// check the UnresolvedTypes list as well.
|
|
if (isOnStack(Ty)) {
|
|
TypeMap::const_iterator I = UnresolvedTypes.find(Ty);
|
|
if (I == UnresolvedTypes.end()) {
|
|
Out << "PATypeHolder " << typeName << "_fwd = OpaqueType::get();\n";
|
|
UnresolvedTypes[Ty] = typeName;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Avoid printing things we have already printed. Since TNI was obtained
|
|
// before the name was inserted with getCppName and because we know the name
|
|
// is not on the stack (currently being defined), we can surmise here that if
|
|
// we got the name we've also already emitted its definition.
|
|
if (TNI != TypeNames.end())
|
|
return false;
|
|
|
|
// 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); // push on type stack
|
|
bool didRecurse = false;
|
|
|
|
// Print the type definition
|
|
switch (Ty->getTypeID()) {
|
|
case Type::FunctionTyID: {
|
|
const FunctionType* FT = cast<FunctionType>(Ty);
|
|
Out << "std::vector<const Type*>" << typeName << "_args;\n";
|
|
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 = printTypeDefInternal(argTy);
|
|
std::string argName(getCppName(argTy));
|
|
Out << typeName << "_args.push_back(" << argName;
|
|
if (isForward)
|
|
Out << "_fwd";
|
|
Out << ");\n";
|
|
}
|
|
bool isForward = printTypeDefInternal(FT->getReturnType());
|
|
std::string retTypeName(getCppName(FT->getReturnType()));
|
|
Out << "FunctionType* " << typeName << " = FunctionType::get(\n"
|
|
<< " /*Result=*/" << retTypeName;
|
|
if (isForward)
|
|
Out << "_fwd";
|
|
Out << ",\n /*Params=*/" << typeName << "_args,\n /*isVarArg=*/"
|
|
<< (FT->isVarArg() ? "true" : "false") << ");\n";
|
|
break;
|
|
}
|
|
case Type::StructTyID: {
|
|
const StructType* ST = cast<StructType>(Ty);
|
|
Out << "std::vector<const Type*>" << typeName << "_fields;\n";
|
|
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 = printTypeDefInternal(fieldTy);
|
|
std::string fieldName(getCppName(fieldTy));
|
|
Out << typeName << "_fields.push_back(" << fieldName;
|
|
if (isForward)
|
|
Out << "_fwd";
|
|
Out << ");\n";
|
|
}
|
|
Out << "StructType* " << typeName << " = StructType::get("
|
|
<< typeName << "_fields);\n";
|
|
break;
|
|
}
|
|
case Type::ArrayTyID: {
|
|
const ArrayType* AT = cast<ArrayType>(Ty);
|
|
const Type* ET = AT->getElementType();
|
|
bool isForward = printTypeDefInternal(ET);
|
|
std::string elemName(getCppName(ET));
|
|
Out << "ArrayType* " << typeName << " = ArrayType::get("
|
|
<< elemName << (isForward ? "_fwd" : "")
|
|
<< ", " << utostr(AT->getNumElements()) << ");\n";
|
|
break;
|
|
}
|
|
case Type::PointerTyID: {
|
|
const PointerType* PT = cast<PointerType>(Ty);
|
|
const Type* ET = PT->getElementType();
|
|
bool isForward = printTypeDefInternal(ET);
|
|
std::string elemName(getCppName(ET));
|
|
Out << "PointerType* " << typeName << " = PointerType::get("
|
|
<< elemName << (isForward ? "_fwd" : "") << ");\n";
|
|
break;
|
|
}
|
|
case Type::PackedTyID: {
|
|
const PackedType* PT = cast<PackedType>(Ty);
|
|
const Type* ET = PT->getElementType();
|
|
bool isForward = printTypeDefInternal(ET);
|
|
std::string elemName(getCppName(ET));
|
|
Out << "PackedType* " << typeName << " = PackedType::get("
|
|
<< elemName << (isForward ? "_fwd" : "")
|
|
<< ", " << utostr(PT->getNumElements()) << ");\n";
|
|
break;
|
|
}
|
|
case Type::OpaqueTyID: {
|
|
const OpaqueType* OT = cast<OpaqueType>(Ty);
|
|
Out << "OpaqueType* " << typeName << " = OpaqueType::get();\n";
|
|
break;
|
|
}
|
|
default:
|
|
assert(!"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 << ");\n";
|
|
|
|
// Pop us off the type stack
|
|
TypeStack.pop_back();
|
|
Out << "\n";
|
|
|
|
// We weren't a recursive type
|
|
return false;
|
|
}
|
|
|
|
void
|
|
CppWriter::printTypes(const Module* M) {
|
|
// 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())
|
|
printTypeDef(I->getInitializer()->getType());
|
|
printTypeDef(I->getType());
|
|
}
|
|
|
|
// Add all the functions to the table
|
|
for (Module::const_iterator FI = TheModule->begin(), FE = TheModule->end();
|
|
FI != FE; ++FI) {
|
|
printTypeDef(FI->getReturnType());
|
|
printTypeDef(FI->getFunctionType());
|
|
// Add all the function arguments
|
|
for(Function::const_arg_iterator AI = FI->arg_begin(),
|
|
AE = FI->arg_end(); AI != AE; ++AI) {
|
|
printTypeDef(AI->getType());
|
|
}
|
|
|
|
// Add all of the basic blocks and instructions
|
|
for (Function::const_iterator BB = FI->begin(),
|
|
E = FI->end(); BB != E; ++BB) {
|
|
printTypeDef(BB->getType());
|
|
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;
|
|
++I) {
|
|
printTypeDef(I->getType());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CppWriter::printConstants(const Module* M) {
|
|
// 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())
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// printConstant - Print out a constant pool entry...
|
|
void CppWriter::printConstant(const Constant *CV) {
|
|
// First, if the constant is in the constant list then we've printed it
|
|
// already and we shouldn't reprint it.
|
|
if (ValueNames.find(CV) != ValueNames.end())
|
|
return;
|
|
|
|
const int IndentSize = 2;
|
|
static std::string Indent = "\n";
|
|
std::string constName(getCppName(CV));
|
|
std::string typeName(getCppName(CV->getType()));
|
|
if (CV->isNullValue()) {
|
|
Out << "Constant* " << constName << " = Constant::getNullValue("
|
|
<< typeName << ");\n";
|
|
return;
|
|
}
|
|
if (isa<GlobalValue>(CV)) {
|
|
// Skip variables and functions, we emit them elsewhere
|
|
return;
|
|
}
|
|
if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
|
|
Out << "Constant* " << constName << " = ConstantBool::get("
|
|
<< (CB == ConstantBool::True ? "true" : "false")
|
|
<< ");";
|
|
} else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV)) {
|
|
Out << "Constant* " << constName << " = ConstantSInt::get("
|
|
<< typeName << ", " << CI->getValue() << ");";
|
|
} else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV)) {
|
|
Out << "Constant* " << constName << " = ConstantUInt::get("
|
|
<< typeName << ", " << CI->getValue() << ");";
|
|
} else if (isa<ConstantAggregateZero>(CV)) {
|
|
Out << "Constant* " << constName << " = ConstantAggregateZero::get("
|
|
<< typeName << ");";
|
|
} else if (isa<ConstantPointerNull>(CV)) {
|
|
Out << "Constant* " << constName << " = ConstanPointerNull::get("
|
|
<< typeName << ");";
|
|
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
|
|
Out << "ConstantFP::get(" << typeName << ", ";
|
|
// We would like to output the FP constant value in exponential notation,
|
|
// but we cannot do this if doing so will lose precision. Check here to
|
|
// make sure that we only output it in exponential format if we can parse
|
|
// the value back and get the same value.
|
|
//
|
|
std::string StrVal = ftostr(CFP->getValue());
|
|
|
|
// Check to make sure that the stringized number is not some string like
|
|
// "Inf" or NaN, that atof will accept, but the lexer will not. 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')))
|
|
// Reparse stringized version!
|
|
if (atof(StrVal.c_str()) == CFP->getValue()) {
|
|
Out << StrVal;
|
|
return;
|
|
}
|
|
|
|
// Otherwise we could not reparse it to exactly the same value, so we must
|
|
// output the string in hexadecimal format!
|
|
assert(sizeof(double) == sizeof(uint64_t) &&
|
|
"assuming that double is 64 bits!");
|
|
Out << "0x" << utohexstr(DoubleToBits(CFP->getValue())) << ");";
|
|
} 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());
|
|
Out << "\");";
|
|
} else {
|
|
Out << "std::vector<Constant*> " << constName << "_elems;\n";
|
|
unsigned N = CA->getNumOperands();
|
|
for (unsigned i = 0; i < N; ++i) {
|
|
printConstant(CA->getOperand(i));
|
|
Out << constName << "_elems.push_back("
|
|
<< getCppName(CA->getOperand(i)) << ");\n";
|
|
}
|
|
Out << "Constant* " << constName << " = ConstantArray::get("
|
|
<< typeName << ", " << constName << "_elems);";
|
|
}
|
|
} else if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(CV)) {
|
|
Out << "std::vector<Constant*> " << constName << "_fields;\n";
|
|
unsigned N = CS->getNumOperands();
|
|
for (unsigned i = 0; i < N; i++) {
|
|
printConstant(CS->getOperand(i));
|
|
Out << constName << "_fields.push_back("
|
|
<< getCppName(CA->getOperand(i)) << ");\n";
|
|
}
|
|
Out << "Constant* " << constName << " = ConstantStruct::get("
|
|
<< typeName << ", " << constName << "_fields);";
|
|
} else if (const ConstantPacked *CP = dyn_cast<ConstantPacked>(CV)) {
|
|
Out << "std::vector<Constant*> " << constName << "_elems;\n";
|
|
unsigned N = CP->getNumOperands();
|
|
for (unsigned i = 0; i < N; ++i) {
|
|
printConstant(CP->getOperand(i));
|
|
Out << constName << "_elems.push_back("
|
|
<< getCppName(CP->getOperand(i)) << ");\n";
|
|
}
|
|
Out << "Constant* " << constName << " = ConstantPacked::get("
|
|
<< typeName << ", " << constName << "_elems);";
|
|
} else if (isa<UndefValue>(CV)) {
|
|
Out << "Constant* " << constName << " = UndefValue::get("
|
|
<< typeName << ");";
|
|
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
|
|
if (CE->getOpcode() == Instruction::GetElementPtr) {
|
|
Out << "std::vector<Constant*> " << constName << "_indices;\n";
|
|
for (unsigned i = 1; i < CE->getNumOperands(); ++i ) {
|
|
Out << constName << "_indices.push_back("
|
|
<< getCppName(CE->getOperand(i)) << ");\n";
|
|
}
|
|
Out << "Constant* " << constName << " = new GetElementPtrInst("
|
|
<< getCppName(CE->getOperand(0)) << ", " << constName << "_indices";
|
|
} else if (CE->getOpcode() == Instruction::Cast) {
|
|
Out << "Constant* " << constName << " = ConstantExpr::getCast(";
|
|
Out << getCppName(CE->getOperand(0)) << ", " << getCppName(CE->getType())
|
|
<< ");";
|
|
} else {
|
|
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::Div: Out << "getDiv"; break;
|
|
case Instruction::Rem: Out << "getRem"; 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:
|
|
assert(!"Invalid constant expression");
|
|
break;
|
|
}
|
|
Out << getCppName(CE->getOperand(0));
|
|
for (unsigned i = 1; i < CE->getNumOperands(); ++i)
|
|
Out << ", " << getCppName(CE->getOperand(i));
|
|
Out << ");";
|
|
}
|
|
} else {
|
|
assert(!"Bad Constant");
|
|
Out << "Constant* " << constName << " = 0; ";
|
|
}
|
|
Out << "\n";
|
|
}
|
|
|
|
/// printFunction - Print all aspects of a function.
|
|
///
|
|
void CppWriter::printFunction(const Function *F) {
|
|
std::string funcTypeName(getCppName(F->getFunctionType()));
|
|
|
|
Out << "Function* ";
|
|
printCppName(F);
|
|
Out << " = new Function(" << funcTypeName << ", " ;
|
|
printLinkageType(F->getLinkage());
|
|
Out << ",\n \"" << F->getName() << "\", mod);\n";
|
|
printCppName(F);
|
|
Out << "->setCallingConv(";
|
|
printCallingConv(F->getCallingConv());
|
|
Out << ");\n";
|
|
if (F->hasSection()) {
|
|
printCppName(F);
|
|
Out << "->setSection(" << F->getSection() << ");\n";
|
|
}
|
|
if (F->getAlignment()) {
|
|
printCppName(F);
|
|
Out << "->setAlignment(" << F->getAlignment() << ");\n";
|
|
}
|
|
|
|
if (!F->isExternal()) {
|
|
Out << "{\n";
|
|
// Create all the argument values
|
|
for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
|
|
AI != AE; ++AI) {
|
|
Out << " Argument* " << getCppName(AI) << " = new Argument("
|
|
<< getCppName(AI->getType()) << ", \"";
|
|
printEscapedString(AI->getName());
|
|
Out << "\", " << getCppName(F) << ");\n";
|
|
}
|
|
// Create all the basic blocks
|
|
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);\n";
|
|
}
|
|
// Output all of its basic blocks... for the function
|
|
for (Function::const_iterator BI = F->begin(), BE = F->end();
|
|
BI != BE; ++BI) {
|
|
// Output all of the instructions in the basic block...
|
|
Out << " {\n";
|
|
for (BasicBlock::const_iterator I = BI->begin(), E = BI->end();
|
|
I != E; ++I) {
|
|
std::string bbname(getCppName(BI));
|
|
printInstruction(I,bbname);
|
|
}
|
|
Out << " }\n";
|
|
}
|
|
Out << "}\n";
|
|
}
|
|
}
|
|
|
|
// 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));
|
|
|
|
switch (I->getOpcode()) {
|
|
case Instruction::Ret: {
|
|
const ReturnInst* ret = cast<ReturnInst>(I);
|
|
Out << " ReturnInst* " << iName << " = new ReturnInst(";
|
|
if (ret->getReturnValue())
|
|
Out << getCppName(ret->getReturnValue()) << ", ";
|
|
Out << bbname << ");";
|
|
break;
|
|
}
|
|
case Instruction::Br: {
|
|
const BranchInst* br = cast<BranchInst>(I);
|
|
Out << " BranchInst* " << iName << " = new BranchInst(" ;
|
|
if (br->getNumOperands() == 3 ) {
|
|
Out << getCppName(br->getOperand(0)) << ", "
|
|
<< getCppName(br->getOperand(1)) << ", "
|
|
<< getCppName(br->getOperand(2)) << ", ";
|
|
|
|
} else if (br->getNumOperands() == 1) {
|
|
Out << getCppName(br->getOperand(0)) << ", ";
|
|
} else {
|
|
assert(!"branch with 2 operands?");
|
|
}
|
|
Out << bbname << ");";
|
|
break;
|
|
}
|
|
case Instruction::Switch:
|
|
case Instruction::Invoke:
|
|
case Instruction::Unwind:
|
|
case Instruction::Unreachable:
|
|
case Instruction::Add:
|
|
case Instruction::Sub:
|
|
case Instruction::Mul:
|
|
case Instruction::Div:
|
|
case Instruction::Rem:
|
|
case Instruction::And:
|
|
case Instruction::Or:
|
|
case Instruction::Xor:
|
|
case Instruction::SetEQ:
|
|
case Instruction::SetNE:
|
|
case Instruction::SetLE:
|
|
case Instruction::SetGE:
|
|
case Instruction::SetLT:
|
|
case Instruction::SetGT:
|
|
break;
|
|
case Instruction::Malloc: {
|
|
const MallocInst* mallocI = cast<MallocInst>(I);
|
|
Out << " MallocInst* " << iName << " = new MallocInst("
|
|
<< getCppName(mallocI->getAllocatedType()) << ", ";
|
|
if (mallocI->isArrayAllocation())
|
|
Out << getCppName(mallocI->getArraySize()) << ", ";
|
|
Out << "\"";
|
|
printEscapedString(mallocI->getName());
|
|
Out << "\", " << bbname << ");";
|
|
if (mallocI->getAlignment())
|
|
Out << "\n " << iName << "->setAlignment("
|
|
<< mallocI->getAlignment() << ");";
|
|
break;
|
|
}
|
|
case Instruction::Free:
|
|
case Instruction::Alloca: {
|
|
const AllocaInst* allocaI = cast<AllocaInst>(I);
|
|
Out << " AllocaInst* " << iName << " = new AllocaInst("
|
|
<< getCppName(allocaI->getAllocatedType()) << ", ";
|
|
if (allocaI->isArrayAllocation())
|
|
Out << getCppName(allocaI->getArraySize()) << ", ";
|
|
Out << "\"";
|
|
printEscapedString(allocaI->getName());
|
|
Out << "\", " << bbname << ");";
|
|
if (allocaI->getAlignment())
|
|
Out << "\n " << iName << "->setAlignment("
|
|
<< allocaI->getAlignment() << ");";
|
|
break;
|
|
}
|
|
case Instruction::Load:
|
|
break;
|
|
case Instruction::Store: {
|
|
const StoreInst* store = cast<StoreInst>(I);
|
|
Out << " StoreInst* " << iName << " = new StoreInst("
|
|
<< getCppName(store->getOperand(0)) << ", "
|
|
<< getCppName(store->getOperand(1)) << ", " << bbname << ");\n";
|
|
if (store->isVolatile())
|
|
Out << "iName->setVolatile(true);";
|
|
break;
|
|
}
|
|
case Instruction::GetElementPtr: {
|
|
const GetElementPtrInst* gep = cast<GetElementPtrInst>(I);
|
|
if (gep->getNumOperands() <= 2) {
|
|
Out << " GetElementPtrInst* " << iName << " = new GetElementPtrInst("
|
|
<< getCppName(gep->getOperand(0));
|
|
if (gep->getNumOperands() == 2)
|
|
Out << ", " << getCppName(gep->getOperand(1));
|
|
Out << ", " << bbname;
|
|
} else {
|
|
Out << " std::vector<Value*> " << iName << "_indices;\n";
|
|
for (unsigned i = 1; i < gep->getNumOperands(); ++i ) {
|
|
Out << " " << iName << "_indices.push_back("
|
|
<< getCppName(gep->getOperand(i)) << ");\n";
|
|
}
|
|
Out << " Instruction* " << iName << " = new GetElementPtrInst("
|
|
<< getCppName(gep->getOperand(0)) << ", " << iName << "_indices";
|
|
}
|
|
Out << ", \"";
|
|
printEscapedString(gep->getName());
|
|
Out << "\", " << bbname << ");";
|
|
break;
|
|
}
|
|
case Instruction::PHI:
|
|
case Instruction::Cast:
|
|
case Instruction::Call:
|
|
case Instruction::Shl:
|
|
case Instruction::Shr:
|
|
case Instruction::Select:
|
|
case Instruction::UserOp1:
|
|
case Instruction::UserOp2:
|
|
case Instruction::VAArg:
|
|
case Instruction::ExtractElement:
|
|
case Instruction::InsertElement:
|
|
case Instruction::ShuffleVector:
|
|
break;
|
|
}
|
|
Out << "\n";
|
|
|
|
/*
|
|
// Print out name if it exists...
|
|
if (I.hasName())
|
|
Out << getLLVMName(I.getName()) << " = ";
|
|
|
|
// If this is a volatile load or store, print out the volatile marker.
|
|
if ((isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) ||
|
|
(isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile())) {
|
|
Out << "volatile ";
|
|
} else if (isa<CallInst>(I) && cast<CallInst>(I).isTailCall()) {
|
|
// If this is a call, check if it's a tail call.
|
|
Out << "tail ";
|
|
}
|
|
|
|
// Print out the opcode...
|
|
Out << I.getOpcodeName();
|
|
|
|
// Print out the type of the operands...
|
|
const Value *Operand = I.getNumOperands() ? I.getOperand(0) : 0;
|
|
|
|
// Special case conditional branches to swizzle the condition out to the front
|
|
if (isa<BranchInst>(I) && I.getNumOperands() > 1) {
|
|
writeOperand(I.getOperand(2), true);
|
|
Out << ',';
|
|
writeOperand(Operand, true);
|
|
Out << ',';
|
|
writeOperand(I.getOperand(1), true);
|
|
|
|
} else if (isa<SwitchInst>(I)) {
|
|
// Special case switch statement to get formatting nice and correct...
|
|
writeOperand(Operand , true); Out << ',';
|
|
writeOperand(I.getOperand(1), true); Out << " [";
|
|
|
|
for (unsigned op = 2, Eop = I.getNumOperands(); op < Eop; op += 2) {
|
|
Out << "\n\t\t";
|
|
writeOperand(I.getOperand(op ), true); Out << ',';
|
|
writeOperand(I.getOperand(op+1), true);
|
|
}
|
|
Out << "\n\t]";
|
|
} else if (isa<PHINode>(I)) {
|
|
Out << ' ';
|
|
printType(I.getType());
|
|
Out << ' ';
|
|
|
|
for (unsigned op = 0, Eop = I.getNumOperands(); op < Eop; op += 2) {
|
|
if (op) Out << ", ";
|
|
Out << '[';
|
|
writeOperand(I.getOperand(op ), false); Out << ',';
|
|
writeOperand(I.getOperand(op+1), false); Out << " ]";
|
|
}
|
|
} else if (isa<ReturnInst>(I) && !Operand) {
|
|
Out << " void";
|
|
} else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
|
|
// Print the calling convention being used.
|
|
switch (CI->getCallingConv()) {
|
|
case CallingConv::C: break; // default
|
|
case CallingConv::CSRet: Out << " csretcc"; break;
|
|
case CallingConv::Fast: Out << " fastcc"; break;
|
|
case CallingConv::Cold: Out << " coldcc"; break;
|
|
default: Out << " cc" << CI->getCallingConv(); break;
|
|
}
|
|
|
|
const PointerType *PTy = cast<PointerType>(Operand->getType());
|
|
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
|
|
const Type *RetTy = FTy->getReturnType();
|
|
|
|
// If possible, print out the short form of the call instruction. We can
|
|
// only do this if the first argument is a pointer to a nonvararg function,
|
|
// and if the return type is not a pointer to a function.
|
|
//
|
|
if (!FTy->isVarArg() &&
|
|
(!isa<PointerType>(RetTy) ||
|
|
!isa<FunctionType>(cast<PointerType>(RetTy)->getElementType()))) {
|
|
Out << ' '; printType(RetTy);
|
|
writeOperand(Operand, false);
|
|
} else {
|
|
writeOperand(Operand, true);
|
|
}
|
|
Out << '(';
|
|
if (CI->getNumOperands() > 1) writeOperand(CI->getOperand(1), true);
|
|
for (unsigned op = 2, Eop = I.getNumOperands(); op < Eop; ++op) {
|
|
Out << ',';
|
|
writeOperand(I.getOperand(op), true);
|
|
}
|
|
|
|
Out << " )";
|
|
} else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
|
|
const PointerType *PTy = cast<PointerType>(Operand->getType());
|
|
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
|
|
const Type *RetTy = FTy->getReturnType();
|
|
|
|
// Print the calling convention being used.
|
|
switch (II->getCallingConv()) {
|
|
case CallingConv::C: break; // default
|
|
case CallingConv::CSRet: Out << " csretcc"; break;
|
|
case CallingConv::Fast: Out << " fastcc"; break;
|
|
case CallingConv::Cold: Out << " coldcc"; break;
|
|
default: Out << " cc" << II->getCallingConv(); break;
|
|
}
|
|
|
|
// If possible, print out the short form of the invoke instruction. We can
|
|
// only do this if the first argument is a pointer to a nonvararg function,
|
|
// and if the return type is not a pointer to a function.
|
|
//
|
|
if (!FTy->isVarArg() &&
|
|
(!isa<PointerType>(RetTy) ||
|
|
!isa<FunctionType>(cast<PointerType>(RetTy)->getElementType()))) {
|
|
Out << ' '; printType(RetTy);
|
|
writeOperand(Operand, false);
|
|
} else {
|
|
writeOperand(Operand, true);
|
|
}
|
|
|
|
Out << '(';
|
|
if (I.getNumOperands() > 3) writeOperand(I.getOperand(3), true);
|
|
for (unsigned op = 4, Eop = I.getNumOperands(); op < Eop; ++op) {
|
|
Out << ',';
|
|
writeOperand(I.getOperand(op), true);
|
|
}
|
|
|
|
Out << " )\n\t\t\tto";
|
|
writeOperand(II->getNormalDest(), true);
|
|
Out << " unwind";
|
|
writeOperand(II->getUnwindDest(), true);
|
|
|
|
} else if (const AllocationInst *AI = dyn_cast<AllocationInst>(&I)) {
|
|
Out << ' ';
|
|
printType(AI->getType()->getElementType());
|
|
if (AI->isArrayAllocation()) {
|
|
Out << ',';
|
|
writeOperand(AI->getArraySize(), true);
|
|
}
|
|
if (AI->getAlignment()) {
|
|
Out << ", align " << AI->getAlignment();
|
|
}
|
|
} else if (isa<CastInst>(I)) {
|
|
if (Operand) writeOperand(Operand, true); // Work with broken code
|
|
Out << " to ";
|
|
printType(I.getType());
|
|
} else if (isa<VAArgInst>(I)) {
|
|
if (Operand) writeOperand(Operand, true); // Work with broken code
|
|
Out << ", ";
|
|
printType(I.getType());
|
|
} else if (Operand) { // Print the normal way...
|
|
|
|
// PrintAllTypes - Instructions who have operands of all the same type
|
|
// omit the type from all but the first operand. If the instruction has
|
|
// different type operands (for example br), then they are all printed.
|
|
bool PrintAllTypes = false;
|
|
const Type *TheType = Operand->getType();
|
|
|
|
// Shift Left & Right print both types even for Ubyte LHS, and select prints
|
|
// types even if all operands are bools.
|
|
if (isa<ShiftInst>(I) || isa<SelectInst>(I) || isa<StoreInst>(I) ||
|
|
isa<ShuffleVectorInst>(I)) {
|
|
PrintAllTypes = true;
|
|
} else {
|
|
for (unsigned i = 1, E = I.getNumOperands(); i != E; ++i) {
|
|
Operand = I.getOperand(i);
|
|
if (Operand->getType() != TheType) {
|
|
PrintAllTypes = true; // We have differing types! Print them all!
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!PrintAllTypes) {
|
|
Out << ' ';
|
|
printType(TheType);
|
|
}
|
|
|
|
for (unsigned i = 0, E = I.getNumOperands(); i != E; ++i) {
|
|
if (i) Out << ',';
|
|
writeOperand(I.getOperand(i), PrintAllTypes);
|
|
}
|
|
}
|
|
|
|
Out << "\n";
|
|
*/
|
|
}
|
|
|
|
} // end anonymous llvm
|
|
|
|
namespace llvm {
|
|
|
|
void WriteModuleToCppFile(Module* mod, std::ostream& o) {
|
|
o << "#include <llvm/Module.h>\n";
|
|
o << "#include <llvm/DerivedTypes.h>\n";
|
|
o << "#include <llvm/Constants.h>\n";
|
|
o << "#include <llvm/GlobalVariable.h>\n";
|
|
o << "#include <llvm/Function.h>\n";
|
|
o << "#include <llvm/CallingConv.h>\n";
|
|
o << "#include <llvm/BasicBlock.h>\n";
|
|
o << "#include <llvm/Instructions.h>\n";
|
|
o << "#include <llvm/Pass.h>\n";
|
|
o << "#include <llvm/PassManager.h>\n";
|
|
o << "#include <llvm/Analysis/Verifier.h>\n";
|
|
o << "#include <llvm/Assembly/PrintModulePass.h>\n";
|
|
o << "#include <algorithm>\n";
|
|
o << "#include <iostream>\n\n";
|
|
o << "using namespace llvm;\n\n";
|
|
o << "Module* makeLLVMModule();\n\n";
|
|
o << "int main(int argc, char**argv) {\n";
|
|
o << " Module* Mod = makeLLVMModule();\n";
|
|
o << " verifyModule(*Mod, PrintMessageAction);\n";
|
|
o << " std::cerr.flush();\n";
|
|
o << " std::cout.flush();\n";
|
|
o << " PassManager PM;\n";
|
|
o << " PM.add(new PrintModulePass(&std::cout));\n";
|
|
o << " PM.run(*Mod);\n";
|
|
o << " return 0;\n";
|
|
o << "}\n\n";
|
|
o << "Module* makeLLVMModule() {\n";
|
|
CppWriter W(o, mod);
|
|
W.printModule(mod);
|
|
o << "return mod;\n";
|
|
o << "}\n";
|
|
}
|
|
|
|
}
|