llvm-project/llvm/lib/Target/CppBackend/CPPBackend.cpp

2146 lines
75 KiB
C++
Raw Normal View History

//===-- CPPBackend.cpp - Library for converting LLVM code to C++ code -----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the writing of the LLVM IR as a set of C++ calls to the
// LLVM IR interface. The input module is assumed to be verified.
//
//===----------------------------------------------------------------------===//
#include "CPPTargetMachine.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/config.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <map>
#include <set>
using namespace llvm;
static cl::opt<std::string>
FuncName("cppfname", 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("cppgen", cl::Optional,
cl::desc("Choose what kind of output to generate"),
cl::init(GenProgram),
cl::values(
clEnumValN(GenProgram, "program", "Generate a complete program"),
clEnumValN(GenModule, "module", "Generate a module definition"),
clEnumValN(GenContents, "contents", "Generate contents of a module"),
clEnumValN(GenFunction, "function", "Generate a function definition"),
clEnumValN(GenFunctions,"functions", "Generate all function definitions"),
clEnumValN(GenInline, "inline", "Generate an inline function"),
clEnumValN(GenVariable, "variable", "Generate a variable definition"),
clEnumValN(GenType, "type", "Generate a type definition"),
clEnumValEnd
)
);
static cl::opt<std::string> NameToGenerate("cppfor", cl::Optional,
cl::desc("Specify the name of the thing to generate"),
cl::init("!bad!"));
extern "C" void LLVMInitializeCppBackendTarget() {
// Register the target.
RegisterTargetMachine<CPPTargetMachine> X(TheCppBackendTarget);
}
namespace {
typedef std::vector<Type*> TypeList;
typedef std::map<Type*,std::string> TypeMap;
typedef std::map<const Value*,std::string> ValueMap;
typedef std::set<std::string> NameSet;
typedef std::set<Type*> TypeSet;
typedef std::set<const Value*> ValueSet;
typedef std::map<const Value*,std::string> ForwardRefMap;
/// CppWriter - This class is the main chunk of code that converts an LLVM
/// module to a C++ translation unit.
class CppWriter : public ModulePass {
std::unique_ptr<formatted_raw_ostream> OutOwner;
formatted_raw_ostream &Out;
const Module *TheModule;
uint64_t uniqueNum;
TypeMap TypeNames;
ValueMap ValueNames;
NameSet UsedNames;
TypeSet DefinedTypes;
ValueSet DefinedValues;
ForwardRefMap ForwardRefs;
bool is_inline;
unsigned indent_level;
public:
static char ID;
explicit CppWriter(std::unique_ptr<formatted_raw_ostream> o)
: ModulePass(ID), OutOwner(std::move(o)), Out(*OutOwner), uniqueNum(0),
is_inline(false), indent_level(0) {}
const char *getPassName() const override { return "C++ backend"; }
bool runOnModule(Module &M) override;
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);
formatted_raw_ostream& nl(formatted_raw_ostream &Out, int delta = 0);
inline void in() { indent_level++; }
inline void out() { if (indent_level >0) indent_level--; }
private:
void printLinkageType(GlobalValue::LinkageTypes LT);
void printVisibilityType(GlobalValue::VisibilityTypes VisTypes);
void printDLLStorageClassType(GlobalValue::DLLStorageClassTypes DSCType);
void printThreadLocalMode(GlobalVariable::ThreadLocalMode TLM);
void printCallingConv(CallingConv::ID cc);
void printEscapedString(const std::string& str);
void printCFP(const ConstantFP* CFP);
std::string getCppName(Type* val);
inline void printCppName(Type* val);
std::string getCppName(const Value* val);
inline void printCppName(const Value* val);
void printAttributes(const AttributeSet &PAL, const std::string &name);
void printType(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(const Value*);
void printModuleBody();
};
} // end anonymous namespace.
formatted_raw_ostream &CppWriter::nl(formatted_raw_ostream &Out, int delta) {
Out << '\n';
if (delta >= 0 || indent_level >= unsigned(-delta))
indent_level += delta;
Out.indent(indent_level);
return Out;
}
static inline void sanitize(std::string &str) {
for (size_t i = 0; i < str.length(); ++i)
if (!isalnum(str[i]) && str[i] != '_')
str[i] = '_';
}
static std::string getTypePrefix(Type *Ty) {
switch (Ty->getTypeID()) {
case Type::VoidTyID: return "void_";
case Type::IntegerTyID:
return "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_";
default: return "other_";
}
}
void CppWriter::error(const std::string& msg) {
report_fatal_error(msg);
}
static inline std::string ftostr(const APFloat& V) {
std::string Buf;
if (&V.getSemantics() == &APFloat::IEEEdouble) {
raw_string_ostream(Buf) << V.convertToDouble();
return Buf;
} else if (&V.getSemantics() == &APFloat::IEEEsingle) {
raw_string_ostream(Buf) << (double)V.convertToFloat();
return Buf;
}
return "<unknown format in ftostr>"; // error
}
// 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) {
bool ignored;
APFloat APF = APFloat(CFP->getValueAPF()); // copy
if (CFP->getType() == Type::getFloatTy(CFP->getContext()))
APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored);
Out << "ConstantFP::get(mod->getContext(), ";
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::getDoubleTy(CFP->getContext()))
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::getDoubleTy(CFP->getContext()))
Out << StrVal;
else
Out << StrVal << "f";
} else if (CFP->getType() == Type::getDoubleTy(CFP->getContext()))
Out << "BitsToDouble(0x"
<< utohexstr(CFP->getValueAPF().bitcastToAPInt().getZExtValue())
<< "ULL) /* " << StrVal << " */";
else
Out << "BitsToFloat(0x"
<< utohexstr((uint32_t)CFP->getValueAPF().
bitcastToAPInt().getZExtValue())
<< "U) /* " << StrVal << " */";
Out << ")";
#if HAVE_PRINTF_A
}
#endif
Out << ")";
}
void CppWriter::printCallingConv(CallingConv::ID 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::PrivateLinkage:
Out << "GlobalValue::PrivateLinkage"; break;
case GlobalValue::AvailableExternallyLinkage:
Out << "GlobalValue::AvailableExternallyLinkage "; break;
case GlobalValue::LinkOnceAnyLinkage:
Out << "GlobalValue::LinkOnceAnyLinkage "; break;
case GlobalValue::LinkOnceODRLinkage:
Out << "GlobalValue::LinkOnceODRLinkage "; break;
case GlobalValue::WeakAnyLinkage:
Out << "GlobalValue::WeakAnyLinkage"; break;
case GlobalValue::WeakODRLinkage:
Out << "GlobalValue::WeakODRLinkage"; break;
case GlobalValue::AppendingLinkage:
Out << "GlobalValue::AppendingLinkage"; break;
case GlobalValue::ExternalLinkage:
Out << "GlobalValue::ExternalLinkage"; break;
case GlobalValue::ExternalWeakLinkage:
Out << "GlobalValue::ExternalWeakLinkage"; break;
case GlobalValue::CommonLinkage:
Out << "GlobalValue::CommonLinkage"; break;
}
}
void CppWriter::printVisibilityType(GlobalValue::VisibilityTypes VisType) {
switch (VisType) {
case GlobalValue::DefaultVisibility:
Out << "GlobalValue::DefaultVisibility";
break;
case GlobalValue::HiddenVisibility:
Out << "GlobalValue::HiddenVisibility";
break;
case GlobalValue::ProtectedVisibility:
Out << "GlobalValue::ProtectedVisibility";
break;
}
}
void CppWriter::printDLLStorageClassType(
GlobalValue::DLLStorageClassTypes DSCType) {
switch (DSCType) {
case GlobalValue::DefaultStorageClass:
Out << "GlobalValue::DefaultStorageClass";
break;
case GlobalValue::DLLImportStorageClass:
Out << "GlobalValue::DLLImportStorageClass";
break;
case GlobalValue::DLLExportStorageClass:
Out << "GlobalValue::DLLExportStorageClass";
break;
}
}
void CppWriter::printThreadLocalMode(GlobalVariable::ThreadLocalMode TLM) {
switch (TLM) {
case GlobalVariable::NotThreadLocal:
Out << "GlobalVariable::NotThreadLocal";
break;
case GlobalVariable::GeneralDynamicTLSModel:
Out << "GlobalVariable::GeneralDynamicTLSModel";
break;
case GlobalVariable::LocalDynamicTLSModel:
Out << "GlobalVariable::LocalDynamicTLSModel";
break;
case GlobalVariable::InitialExecTLSModel:
Out << "GlobalVariable::InitialExecTLSModel";
break;
case GlobalVariable::LocalExecTLSModel:
Out << "GlobalVariable::LocalExecTLSModel";
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(Type* Ty) {
switch (Ty->getTypeID()) {
default:
break;
case Type::VoidTyID:
return "Type::getVoidTy(mod->getContext())";
case Type::IntegerTyID: {
unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth();
return "IntegerType::get(mod->getContext(), " + utostr(BitWidth) + ")";
}
case Type::X86_FP80TyID:
return "Type::getX86_FP80Ty(mod->getContext())";
case Type::FloatTyID:
return "Type::getFloatTy(mod->getContext())";
case Type::DoubleTyID:
return "Type::getDoubleTy(mod->getContext())";
case Type::LabelTyID:
return "Type::getLabelTy(mod->getContext())";
case Type::X86_MMXTyID:
return "Type::getX86_MMXTy(mod->getContext())";
}
// 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 = nullptr;
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::VectorTyID: prefix = "VectorTy_"; break;
default: prefix = "OtherTy_"; break; // prevent breakage
}
// See if the type has a name in the symboltable and build accordingly
std::string name;
if (StructType *STy = dyn_cast<StructType>(Ty))
if (STy->hasName())
name = STy->getName();
if (name.empty())
name = utostr(uniqueNum++);
name = std::string(prefix) + name;
sanitize(name);
// Save the name
return TypeNames[Ty] = name;
}
void CppWriter::printCppName(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->getValueType());
} 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());
}
if (val->hasName())
name += val->getName();
else
name += 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::printAttributes(const AttributeSet &PAL,
const std::string &name) {
Out << "AttributeSet " << name << "_PAL;";
nl(Out);
if (!PAL.isEmpty()) {
Out << '{'; in(); nl(Out);
Out << "SmallVector<AttributeSet, 4> Attrs;"; nl(Out);
Out << "AttributeSet PAS;"; in(); nl(Out);
for (unsigned i = 0; i < PAL.getNumSlots(); ++i) {
unsigned index = PAL.getSlotIndex(i);
AttrBuilder attrs(PAL.getSlotAttributes(i), index);
Out << "{"; in(); nl(Out);
Out << "AttrBuilder B;"; nl(Out);
#define HANDLE_ATTR(X) \
if (attrs.contains(Attribute::X)) { \
Out << "B.addAttribute(Attribute::" #X ");"; nl(Out); \
attrs.removeAttribute(Attribute::X); \
}
HANDLE_ATTR(SExt);
HANDLE_ATTR(ZExt);
HANDLE_ATTR(NoReturn);
HANDLE_ATTR(InReg);
HANDLE_ATTR(StructRet);
HANDLE_ATTR(NoUnwind);
HANDLE_ATTR(NoAlias);
HANDLE_ATTR(ByVal);
HANDLE_ATTR(InAlloca);
HANDLE_ATTR(Nest);
HANDLE_ATTR(ReadNone);
HANDLE_ATTR(ReadOnly);
HANDLE_ATTR(NoInline);
HANDLE_ATTR(AlwaysInline);
HANDLE_ATTR(OptimizeNone);
HANDLE_ATTR(OptimizeForSize);
HANDLE_ATTR(StackProtect);
HANDLE_ATTR(StackProtectReq);
HANDLE_ATTR(StackProtectStrong);
Protection against stack-based memory corruption errors using SafeStack This patch adds the safe stack instrumentation pass to LLVM, which separates the program stack into a safe stack, which stores return addresses, register spills, and local variables that are statically verified to be accessed in a safe way, and the unsafe stack, which stores everything else. Such separation makes it much harder for an attacker to corrupt objects on the safe stack, including function pointers stored in spilled registers and return addresses. You can find more information about the safe stack, as well as other parts of or control-flow hijack protection technique in our OSDI paper on code-pointer integrity (http://dslab.epfl.ch/pubs/cpi.pdf) and our project website (http://levee.epfl.ch). The overhead of our implementation of the safe stack is very close to zero (0.01% on the Phoronix benchmarks). This is lower than the overhead of stack cookies, which are supported by LLVM and are commonly used today, yet the security guarantees of the safe stack are strictly stronger than stack cookies. In some cases, the safe stack improves performance due to better cache locality. Our current implementation of the safe stack is stable and robust, we used it to recompile multiple projects on Linux including Chromium, and we also recompiled the entire FreeBSD user-space system and more than 100 packages. We ran unit tests on the FreeBSD system and many of the packages and observed no errors caused by the safe stack. The safe stack is also fully binary compatible with non-instrumented code and can be applied to parts of a program selectively. This patch is our implementation of the safe stack on top of LLVM. The patches make the following changes: - Add the safestack function attribute, similar to the ssp, sspstrong and sspreq attributes. - Add the SafeStack instrumentation pass that applies the safe stack to all functions that have the safestack attribute. This pass moves all unsafe local variables to the unsafe stack with a separate stack pointer, whereas all safe variables remain on the regular stack that is managed by LLVM as usual. - Invoke the pass as the last stage before code generation (at the same time the existing cookie-based stack protector pass is invoked). - Add unit tests for the safe stack. Original patch by Volodymyr Kuznetsov and others at the Dependable Systems Lab at EPFL; updates and upstreaming by myself. Differential Revision: http://reviews.llvm.org/D6094 llvm-svn: 239761
2015-06-16 05:07:11 +08:00
HANDLE_ATTR(SafeStack);
HANDLE_ATTR(NoCapture);
HANDLE_ATTR(NoRedZone);
HANDLE_ATTR(NoImplicitFloat);
HANDLE_ATTR(Naked);
HANDLE_ATTR(InlineHint);
HANDLE_ATTR(ReturnsTwice);
HANDLE_ATTR(UWTable);
HANDLE_ATTR(NonLazyBind);
HANDLE_ATTR(MinSize);
#undef HANDLE_ATTR
if (attrs.contains(Attribute::StackAlignment)) {
Out << "B.addStackAlignmentAttr(" << attrs.getStackAlignment()<<')';
nl(Out);
attrs.removeAttribute(Attribute::StackAlignment);
}
Out << "PAS = AttributeSet::get(mod->getContext(), ";
if (index == ~0U)
Out << "~0U,";
else
Out << index << "U,";
Out << " B);"; out(); nl(Out);
Out << "}"; out(); nl(Out);
nl(Out);
Out << "Attrs.push_back(PAS);"; nl(Out);
}
Out << name << "_PAL = AttributeSet::get(mod->getContext(), Attrs);";
nl(Out);
out(); nl(Out);
Out << '}'; nl(Out);
}
}
void CppWriter::printType(Type* Ty) {
// We don't print definitions for primitive types
if (Ty->isFloatingPointTy() || Ty->isX86_MMXTy() || Ty->isIntegerTy() ||
[IR] Add token types This introduces the basic functionality to support "token types". The motivation stems from the need to perform operations on a Value whose provenance cannot be obscured. There are several applications for such a type but my immediate motivation stems from WinEH. Our personality routine enforces a single-entry - single-exit regime for cleanups. After several rounds of optimizations, we may be left with a terminator whose "cleanup-entry block" is not entirely clear because control flow has merged two cleanups together. We have experimented with using labels as operands inside of instructions which are not terminators to indicate where we came from but found that LLVM does not expect such exotic uses of BasicBlocks. Instead, we can use this new type to clearly associate the "entry point" and "exit point" of our cleanup. This is done by having the cleanuppad yield a Token and consuming it at the cleanupret. The token type makes it impossible to obscure or otherwise hide the Value, making it trivial to track the relationship between the two points. What is the burden to the optimizer? Well, it turns out we have already paid down this cost by accepting that there are certain calls that we are not permitted to duplicate, optimizations have to watch out for such instructions anyway. There are additional places in the optimizer that we will probably have to update but early examination has given me the impression that this will not be heroic. Differential Revision: http://reviews.llvm.org/D11861 llvm-svn: 245029
2015-08-14 13:09:07 +08:00
Ty->isLabelTy() || Ty->isMetadataTy() || Ty->isVoidTy() ||
Ty->isTokenTy())
return;
// If we already defined this type, we don't need to define it again.
if (DefinedTypes.find(Ty) != DefinedTypes.end())
return;
// Everything below needs the name for the type so get it now.
std::string typeName(getCppName(Ty));
// Print the type definition
switch (Ty->getTypeID()) {
case Type::FunctionTyID: {
FunctionType* FT = cast<FunctionType>(Ty);
Out << "std::vector<Type*>" << typeName << "_args;";
nl(Out);
FunctionType::param_iterator PI = FT->param_begin();
FunctionType::param_iterator PE = FT->param_end();
for (; PI != PE; ++PI) {
Type* argTy = static_cast<Type*>(*PI);
printType(argTy);
std::string argName(getCppName(argTy));
Out << typeName << "_args.push_back(" << argName;
Out << ");";
nl(Out);
}
printType(FT->getReturnType());
std::string retTypeName(getCppName(FT->getReturnType()));
Out << "FunctionType* " << typeName << " = FunctionType::get(";
in(); nl(Out) << "/*Result=*/" << retTypeName;
Out << ",";
nl(Out) << "/*Params=*/" << typeName << "_args,";
nl(Out) << "/*isVarArg=*/" << (FT->isVarArg() ? "true" : "false") << ");";
out();
nl(Out);
break;
}
case Type::StructTyID: {
StructType* ST = cast<StructType>(Ty);
if (!ST->isLiteral()) {
Out << "StructType *" << typeName << " = mod->getTypeByName(\"";
printEscapedString(ST->getName());
Out << "\");";
nl(Out);
Out << "if (!" << typeName << ") {";
nl(Out);
Out << typeName << " = ";
Out << "StructType::create(mod->getContext(), \"";
printEscapedString(ST->getName());
Out << "\");";
nl(Out);
Out << "}";
nl(Out);
// Indicate that this type is now defined.
DefinedTypes.insert(Ty);
}
Out << "std::vector<Type*>" << typeName << "_fields;";
nl(Out);
StructType::element_iterator EI = ST->element_begin();
StructType::element_iterator EE = ST->element_end();
for (; EI != EE; ++EI) {
Type* fieldTy = static_cast<Type*>(*EI);
printType(fieldTy);
std::string fieldName(getCppName(fieldTy));
Out << typeName << "_fields.push_back(" << fieldName;
Out << ");";
nl(Out);
}
if (ST->isLiteral()) {
Out << "StructType *" << typeName << " = ";
Out << "StructType::get(" << "mod->getContext(), ";
} else {
Out << "if (" << typeName << "->isOpaque()) {";
nl(Out);
Out << typeName << "->setBody(";
}
Out << typeName << "_fields, /*isPacked=*/"
<< (ST->isPacked() ? "true" : "false") << ");";
nl(Out);
if (!ST->isLiteral()) {
Out << "}";
nl(Out);
}
break;
}
case Type::ArrayTyID: {
ArrayType* AT = cast<ArrayType>(Ty);
Type* ET = AT->getElementType();
printType(ET);
if (DefinedTypes.find(Ty) == DefinedTypes.end()) {
std::string elemName(getCppName(ET));
Out << "ArrayType* " << typeName << " = ArrayType::get("
<< elemName << ", " << AT->getNumElements() << ");";
nl(Out);
}
break;
}
case Type::PointerTyID: {
PointerType* PT = cast<PointerType>(Ty);
Type* ET = PT->getElementType();
printType(ET);
if (DefinedTypes.find(Ty) == DefinedTypes.end()) {
std::string elemName(getCppName(ET));
Out << "PointerType* " << typeName << " = PointerType::get("
<< elemName << ", " << PT->getAddressSpace() << ");";
nl(Out);
}
break;
}
case Type::VectorTyID: {
VectorType* PT = cast<VectorType>(Ty);
Type* ET = PT->getElementType();
printType(ET);
if (DefinedTypes.find(Ty) == DefinedTypes.end()) {
std::string elemName(getCppName(ET));
Out << "VectorType* " << typeName << " = VectorType::get("
<< elemName << ", " << PT->getNumElements() << ");";
nl(Out);
}
break;
}
default:
error("Invalid TypeID");
}
// Indicate that this type is now defined.
DefinedTypes.insert(Ty);
// Finally, separate the type definition from other with a newline.
nl(Out);
}
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())
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 (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
std::string constValue = CI->getValue().toString(10, true);
Out << "ConstantInt* " << constName
<< " = ConstantInt::get(mod->getContext(), APInt("
<< cast<IntegerType>(CI->getType())->getBitWidth()
<< ", StringRef(\"" << constValue << "\"), 10));";
} else if (isa<ConstantAggregateZero>(CV)) {
Out << "ConstantAggregateZero* " << constName
<< " = ConstantAggregateZero::get(" << typeName << ");";
} else if (isa<ConstantPointerNull>(CV)) {
Out << "ConstantPointerNull* " << constName
<< " = ConstantPointerNull::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)) {
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 *CVec = dyn_cast<ConstantVector>(CV)) {
Out << "std::vector<Constant*> " << constName << "_elems;";
nl(Out);
unsigned N = CVec->getNumOperands();
for (unsigned i = 0; i < N; ++i) {
printConstant(CVec->getOperand(i));
Out << constName << "_elems.push_back("
<< getCppName(CVec->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 ConstantDataSequential *CDS =
dyn_cast<ConstantDataSequential>(CV)) {
if (CDS->isString()) {
Out << "Constant *" << constName <<
" = ConstantDataArray::getString(mod->getContext(), \"";
StringRef Str = CDS->getAsString();
bool nullTerminate = false;
if (Str.back() == 0) {
Str = Str.drop_back();
nullTerminate = true;
}
printEscapedString(Str);
// Determine if we want null termination or not.
if (nullTerminate)
Out << "\", true);";
else
Out << "\", false);";// No null terminator
} else {
// TODO: Could generate more efficient code generating CDS calls instead.
Out << "std::vector<Constant*> " << constName << "_elems;";
nl(Out);
for (unsigned i = 0; i != CDS->getNumElements(); ++i) {
Constant *Elt = CDS->getElementAsConstant(i);
printConstant(Elt);
Out << constName << "_elems.push_back(" << getCppName(Elt) << ");";
nl(Out);
}
Out << "Constant* " << constName;
if (isa<ArrayType>(CDS->getType()))
Out << " = ConstantArray::get(";
else
Out << " = ConstantVector::get(";
Out << typeName << ", " << constName << "_elems);";
}
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
if (CE->getOpcode() == Instruction::GetElementPtr) {
Out << "std::vector<Constant*> " << constName << "_indices;";
nl(Out);
printConstant(CE->getOperand(0));
for (unsigned i = 1; i < CE->getNumOperands(); ++i ) {
printConstant(CE->getOperand(i));
Out << constName << "_indices.push_back("
<< getCppName(CE->getOperand(i)) << ");";
nl(Out);
}
Out << "Constant* " << constName
<< " = ConstantExpr::getGetElementPtr("
<< getCppName(CE->getOperand(0)) << ", "
<< constName << "_indices);";
} else if (CE->isCast()) {
printConstant(CE->getOperand(0));
Out << "Constant* " << constName << " = ConstantExpr::getCast(";
switch (CE->getOpcode()) {
default: llvm_unreachable("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::FAdd: Out << "getFAdd("; break;
case Instruction::Sub: Out << "getSub("; break;
case Instruction::FSub: Out << "getFSub("; break;
case Instruction::Mul: Out << "getMul("; break;
case Instruction::FMul: Out << "getFMul("; 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 if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) {
Out << "Constant* " << constName << " = ";
Out << "BlockAddress::get(" << getOpName(BA->getBasicBlock()) << ");";
} 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()) {
const Constant *Init = GV->getInitializer();
printType(Init->getType());
if (const Function *F = dyn_cast<Function>(Init)) {
nl(Out)<< "/ Function Declarations"; nl(Out);
printFunctionHead(F);
} else if (const GlobalVariable* gv = dyn_cast<GlobalVariable>(Init)) {
nl(Out) << "// Global Variable Declarations"; nl(Out);
printVariableHead(gv);
nl(Out) << "// Global Variable Definitions"; nl(Out);
printVariableBody(gv);
} else {
nl(Out) << "// Constant Definitions"; nl(Out);
printConstant(Init);
}
}
}
void CppWriter::printVariableHead(const GlobalVariable *GV) {
nl(Out) << "GlobalVariable* " << getCppName(GV);
if (is_inline) {
Out << " = mod->getGlobalVariable(mod->getContext(), ";
printEscapedString(GV->getName());
Out << ", " << getCppName(GV->getValueType()) << ",true)";
nl(Out) << "if (!" << getCppName(GV) << ") {";
in(); nl(Out) << getCppName(GV);
}
Out << " = new GlobalVariable(/*Module=*/*mod, ";
nl(Out) << "/*Type=*/";
printCppName(GV->getValueType());
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);
if (GV->hasSection()) {
printCppName(GV);
Out << "->setSection(\"";
printEscapedString(GV->getSection());
Out << "\");";
nl(Out);
}
if (GV->getAlignment()) {
printCppName(GV);
Out << "->setAlignment(" << GV->getAlignment() << ");";
nl(Out);
}
if (GV->getVisibility() != GlobalValue::DefaultVisibility) {
printCppName(GV);
Out << "->setVisibility(";
printVisibilityType(GV->getVisibility());
Out << ");";
nl(Out);
}
if (GV->getDLLStorageClass() != GlobalValue::DefaultStorageClass) {
printCppName(GV);
Out << "->setDLLStorageClass(";
printDLLStorageClassType(GV->getDLLStorageClass());
Out << ");";
nl(Out);
}
if (GV->isThreadLocal()) {
printCppName(GV);
Out << "->setThreadLocalMode(";
printThreadLocalMode(GV->getThreadLocalMode());
Out << ");";
nl(Out);
}
if (is_inline) {
out(); Out << "}"; nl(Out);
}
}
void CppWriter::printVariableBody(const GlobalVariable *GV) {
if (GV->hasInitializer()) {
printCppName(GV);
Out << "->setInitializer(";
Out << getCppName(GV->getInitializer()) << ");";
nl(Out);
}
}
std::string CppWriter::getOpName(const 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;
}
static StringRef ConvertAtomicOrdering(AtomicOrdering Ordering) {
switch (Ordering) {
case AtomicOrdering::NotAtomic: return "NotAtomic";
case AtomicOrdering::Unordered: return "Unordered";
case AtomicOrdering::Monotonic: return "Monotonic";
case AtomicOrdering::Acquire: return "Acquire";
case AtomicOrdering::Release: return "Release";
case AtomicOrdering::AcquireRelease: return "AcquireRelease";
case AtomicOrdering::SequentiallyConsistent:
return "SequentiallyConsistent";
}
llvm_unreachable("Unknown ordering");
}
static StringRef ConvertAtomicSynchScope(SynchronizationScope SynchScope) {
switch (SynchScope) {
case SingleThread: return "SingleThread";
case CrossThread: return "CrossThread";
}
llvm_unreachable("Unknown synch scope");
}
// 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
const unsigned Ops(I->getNumOperands());
std::string* opNames = new std::string[Ops];
for (unsigned i = 0; i < Ops; i++)
opNames[i] = getOpName(I->getOperand(i));
switch (I->getOpcode()) {
default:
error("Invalid instruction");
break;
case Instruction::Ret: {
const ReturnInst* ret = cast<ReturnInst>(I);
Out << "ReturnInst::Create(mod->getContext(), "
<< (ret->getReturnValue() ? opNames[0] + ", " : "") << bbname << ");";
break;
}
case Instruction::Br: {
const BranchInst* br = cast<BranchInst>(I);
Out << "BranchInst::Create(" ;
if (br->getNumOperands() == 3) {
Out << opNames[2] << ", "
<< opNames[1] << ", "
<< opNames[0] << ", ";
} else if (br->getNumOperands() == 1) {
Out << opNames[0] << ", ";
} else {
error("Branch with 2 operands?");
}
Out << bbname << ");";
break;
}
case Instruction::Switch: {
const SwitchInst *SI = cast<SwitchInst>(I);
Out << "SwitchInst* " << iName << " = SwitchInst::Create("
<< getOpName(SI->getCondition()) << ", "
<< getOpName(SI->getDefaultDest()) << ", "
<< SI->getNumCases() << ", " << bbname << ");";
nl(Out);
for (SwitchInst::ConstCaseIt i = SI->case_begin(), e = SI->case_end();
i != e; ++i) {
const ConstantInt* CaseVal = i.getCaseValue();
const BasicBlock *BB = i.getCaseSuccessor();
Out << iName << "->addCase("
<< getOpName(CaseVal) << ", "
<< getOpName(BB) << ");";
nl(Out);
}
break;
}
case Instruction::IndirectBr: {
const IndirectBrInst *IBI = cast<IndirectBrInst>(I);
Out << "IndirectBrInst *" << iName << " = IndirectBrInst::Create("
<< opNames[0] << ", " << IBI->getNumDestinations() << ");";
nl(Out);
for (unsigned i = 1; i != IBI->getNumOperands(); ++i) {
Out << iName << "->addDestination(" << opNames[i] << ");";
nl(Out);
}
break;
}
case Instruction::Resume: {
Out << "ResumeInst::Create(" << opNames[0] << ", " << bbname << ");";
break;
}
case Instruction::Invoke: {
const InvokeInst* inv = cast<InvokeInst>(I);
Out << "std::vector<Value*> " << iName << "_params;";
nl(Out);
for (unsigned i = 0; i < inv->getNumArgOperands(); ++i) {
Out << iName << "_params.push_back("
<< getOpName(inv->getArgOperand(i)) << ");";
nl(Out);
}
// FIXME: This shouldn't use magic numbers -3, -2, and -1.
Out << "InvokeInst *" << iName << " = InvokeInst::Create("
<< getOpName(inv->getCalledValue()) << ", "
<< getOpName(inv->getNormalDest()) << ", "
<< getOpName(inv->getUnwindDest()) << ", "
<< iName << "_params, \"";
printEscapedString(inv->getName());
Out << "\", " << bbname << ");";
nl(Out) << iName << "->setCallingConv(";
printCallingConv(inv->getCallingConv());
Out << ");";
printAttributes(inv->getAttributes(), iName);
Out << iName << "->setAttributes(" << iName << "_PAL);";
nl(Out);
break;
}
case Instruction::Unreachable: {
Out << "new UnreachableInst("
<< "mod->getContext(), "
<< bbname << ");";
break;
}
case Instruction::Add:
case Instruction::FAdd:
case Instruction::Sub:
case Instruction::FSub:
case Instruction::Mul:
case Instruction::FMul:
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::FAdd: Out << "Instruction::FAdd"; break;
case Instruction::Sub: Out << "Instruction::Sub"; break;
case Instruction::FSub: Out << "Instruction::FSub"; break;
case Instruction::Mul: Out << "Instruction::Mul"; break;
case Instruction::FMul: Out << "Instruction::FMul"; 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(*" << bbname << ", ";
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 << "\");";
break;
}
case Instruction::ICmp: {
Out << "ICmpInst* " << iName << " = new ICmpInst(*" << bbname << ", ";
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 << "\");";
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;
}
2010-06-26 20:17:21 +08:00
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 << ");";
if (load->getAlignment())
nl(Out) << iName << "->setAlignment("
<< load->getAlignment() << ");";
if (load->isAtomic()) {
StringRef Ordering = ConvertAtomicOrdering(load->getOrdering());
StringRef CrossThread = ConvertAtomicSynchScope(load->getSynchScope());
nl(Out) << iName << "->setAtomic("
<< Ordering << ", " << CrossThread << ");";
}
break;
}
case Instruction::Store: {
const StoreInst* store = cast<StoreInst>(I);
Out << "StoreInst* " << iName << " = new StoreInst("
<< opNames[0] << ", "
<< opNames[1] << ", "
<< (store->isVolatile() ? "true" : "false")
<< ", " << bbname << ");";
if (store->getAlignment())
nl(Out) << iName << "->setAlignment("
<< store->getAlignment() << ");";
if (store->isAtomic()) {
StringRef Ordering = ConvertAtomicOrdering(store->getOrdering());
StringRef CrossThread = ConvertAtomicSynchScope(store->getSynchScope());
nl(Out) << iName << "->setAtomic("
<< Ordering << ", " << CrossThread << ");";
}
break;
}
case Instruction::GetElementPtr: {
const GetElementPtrInst* gep = cast<GetElementPtrInst>(I);
Out << "GetElementPtrInst* " << iName << " = GetElementPtrInst::Create("
<< getCppName(gep->getSourceElementType()) << ", " << opNames[0] << ", {";
in();
for (unsigned i = 1; i < gep->getNumOperands(); ++i ) {
if (i != 1) {
Out << ", ";
}
nl(Out);
Out << opNames[i];
}
out();
nl(Out) << "}, \"";
printEscapedString(gep->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::PHI: {
const PHINode* phi = cast<PHINode>(I);
Out << "PHINode* " << iName << " = PHINode::Create("
<< getCppName(phi->getType()) << ", "
<< phi->getNumIncomingValues() << ", \"";
printEscapedString(phi->getName());
Out << "\", " << bbname << ");";
nl(Out);
for (unsigned i = 0; i < phi->getNumIncomingValues(); ++i) {
Out << iName << "->addIncoming("
<< opNames[PHINode::getOperandNumForIncomingValue(i)] << ", "
<< getOpName(phi->getIncomingBlock(i)) << ");";
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: llvm_unreachable("Unreachable");
}
Out << "(" << opNames[0] << ", "
<< getCppName(cst->getType()) << ", \"";
printEscapedString(cst->getName());
Out << "\", " << bbname << ");";
break;
}
2010-06-26 20:17:21 +08:00
case Instruction::Call: {
const CallInst* call = cast<CallInst>(I);
if (const InlineAsm* ila = dyn_cast<InlineAsm>(call->getCalledValue())) {
Out << "InlineAsm* " << getCppName(ila) << " = InlineAsm::get("
<< getCppName(ila->getFunctionType()) << ", \""
<< ila->getAsmString() << "\", \""
<< ila->getConstraintString() << "\","
<< (ila->hasSideEffects() ? "true" : "false") << ");";
nl(Out);
}
2010-06-26 20:17:21 +08:00
if (call->getNumArgOperands() > 1) {
Out << "std::vector<Value*> " << iName << "_params;";
nl(Out);
2010-07-03 03:08:46 +08:00
for (unsigned i = 0; i < call->getNumArgOperands(); ++i) {
Out << iName << "_params.push_back(" << opNames[i] << ");";
nl(Out);
}
Out << "CallInst* " << iName << " = CallInst::Create("
<< opNames[call->getNumArgOperands()] << ", "
<< iName << "_params, \"";
2010-06-26 20:17:21 +08:00
} else if (call->getNumArgOperands() == 1) {
Out << "CallInst* " << iName << " = CallInst::Create("
<< opNames[call->getNumArgOperands()] << ", " << opNames[0] << ", \"";
} else {
Out << "CallInst* " << iName << " = CallInst::Create("
<< opNames[call->getNumArgOperands()] << ", \"";
}
printEscapedString(call->getName());
Out << "\", " << bbname << ");";
nl(Out) << iName << "->setCallingConv(";
printCallingConv(call->getCallingConv());
Out << ");";
nl(Out) << iName << "->setTailCall("
2010-06-26 20:17:21 +08:00
<< (call->isTailCall() ? "true" : "false");
Out << ");";
2010-07-03 03:26:28 +08:00
nl(Out);
printAttributes(call->getAttributes(), iName);
Out << iName << "->setAttributes(" << iName << "_PAL);";
nl(Out);
break;
}
case Instruction::Select: {
const SelectInst* sel = cast<SelectInst>(I);
Out << "SelectInst* " << getCppName(sel) << " = SelectInst::Create(";
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)
<< " = InsertElementInst::Create(" << 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;
}
case Instruction::ExtractValue: {
const ExtractValueInst *evi = cast<ExtractValueInst>(I);
Out << "std::vector<unsigned> " << iName << "_indices;";
nl(Out);
for (unsigned i = 0; i < evi->getNumIndices(); ++i) {
Out << iName << "_indices.push_back("
<< evi->idx_begin()[i] << ");";
nl(Out);
}
Out << "ExtractValueInst* " << getCppName(evi)
<< " = ExtractValueInst::Create(" << opNames[0]
<< ", "
<< iName << "_indices, \"";
printEscapedString(evi->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::InsertValue: {
const InsertValueInst *ivi = cast<InsertValueInst>(I);
Out << "std::vector<unsigned> " << iName << "_indices;";
nl(Out);
for (unsigned i = 0; i < ivi->getNumIndices(); ++i) {
Out << iName << "_indices.push_back("
<< ivi->idx_begin()[i] << ");";
nl(Out);
}
Out << "InsertValueInst* " << getCppName(ivi)
<< " = InsertValueInst::Create(" << opNames[0]
<< ", " << opNames[1] << ", "
<< iName << "_indices, \"";
printEscapedString(ivi->getName());
Out << "\", " << bbname << ");";
break;
}
case Instruction::Fence: {
const FenceInst *fi = cast<FenceInst>(I);
StringRef Ordering = ConvertAtomicOrdering(fi->getOrdering());
StringRef CrossThread = ConvertAtomicSynchScope(fi->getSynchScope());
Out << "FenceInst* " << iName
<< " = new FenceInst(mod->getContext(), "
<< Ordering << ", " << CrossThread << ", " << bbname
<< ");";
break;
}
case Instruction::AtomicCmpXchg: {
const AtomicCmpXchgInst *cxi = cast<AtomicCmpXchgInst>(I);
StringRef SuccessOrdering =
ConvertAtomicOrdering(cxi->getSuccessOrdering());
StringRef FailureOrdering =
ConvertAtomicOrdering(cxi->getFailureOrdering());
StringRef CrossThread = ConvertAtomicSynchScope(cxi->getSynchScope());
Out << "AtomicCmpXchgInst* " << iName
<< " = new AtomicCmpXchgInst("
<< opNames[0] << ", " << opNames[1] << ", " << opNames[2] << ", "
<< SuccessOrdering << ", " << FailureOrdering << ", "
<< CrossThread << ", " << bbname
<< ");";
nl(Out) << iName << "->setName(\"";
printEscapedString(cxi->getName());
Out << "\");";
nl(Out) << iName << "->setVolatile("
<< (cxi->isVolatile() ? "true" : "false") << ");";
nl(Out) << iName << "->setWeak("
<< (cxi->isWeak() ? "true" : "false") << ");";
break;
}
case Instruction::AtomicRMW: {
const AtomicRMWInst *rmwi = cast<AtomicRMWInst>(I);
StringRef Ordering = ConvertAtomicOrdering(rmwi->getOrdering());
StringRef CrossThread = ConvertAtomicSynchScope(rmwi->getSynchScope());
StringRef Operation;
switch (rmwi->getOperation()) {
case AtomicRMWInst::Xchg: Operation = "AtomicRMWInst::Xchg"; break;
case AtomicRMWInst::Add: Operation = "AtomicRMWInst::Add"; break;
case AtomicRMWInst::Sub: Operation = "AtomicRMWInst::Sub"; break;
case AtomicRMWInst::And: Operation = "AtomicRMWInst::And"; break;
case AtomicRMWInst::Nand: Operation = "AtomicRMWInst::Nand"; break;
case AtomicRMWInst::Or: Operation = "AtomicRMWInst::Or"; break;
case AtomicRMWInst::Xor: Operation = "AtomicRMWInst::Xor"; break;
case AtomicRMWInst::Max: Operation = "AtomicRMWInst::Max"; break;
case AtomicRMWInst::Min: Operation = "AtomicRMWInst::Min"; break;
case AtomicRMWInst::UMax: Operation = "AtomicRMWInst::UMax"; break;
case AtomicRMWInst::UMin: Operation = "AtomicRMWInst::UMin"; break;
case AtomicRMWInst::BAD_BINOP: llvm_unreachable("Bad atomic operation");
}
Out << "AtomicRMWInst* " << iName
<< " = new AtomicRMWInst("
<< Operation << ", "
<< opNames[0] << ", " << opNames[1] << ", "
<< Ordering << ", " << CrossThread << ", " << bbname
<< ");";
nl(Out) << iName << "->setName(\"";
printEscapedString(rmwi->getName());
Out << "\");";
nl(Out) << iName << "->setVolatile("
<< (rmwi->isVolatile() ? "true" : "false") << ");";
break;
}
case Instruction::LandingPad: {
const LandingPadInst *lpi = cast<LandingPadInst>(I);
Out << "LandingPadInst* " << iName << " = LandingPadInst::Create(";
printCppName(lpi->getType());
Out << ", " << opNames[0] << ", " << lpi->getNumClauses() << ", \"";
printEscapedString(lpi->getName());
Out << "\", " << bbname << ");";
nl(Out) << iName << "->setCleanup("
<< (lpi->isCleanup() ? "true" : "false")
<< ");";
for (unsigned i = 0, e = lpi->getNumClauses(); i != e; ++i)
nl(Out) << iName << "->addClause(" << opNames[i+1] << ");";
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*,32> gvs;
SmallPtrSet<Constant*,32> 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 (GenerationType != GenFunction)
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);
for (Value* operand : C->operands()) {
// If the operand references a GVal or Constant, make a note of it
printType(operand->getType());
if (GlobalValue* GV = dyn_cast<GlobalValue>(operand)) {
gvs.insert(GV);
if (GenerationType != GenFunction)
if (GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
if (GVar->hasInitializer())
consts.insert(GVar->getInitializer());
}
}
}
}
}
}
// Print the function declarations for any functions encountered
nl(Out) << "// Function Declarations"; nl(Out);
2014-05-09 02:40:06 +08:00
for (auto *GV : gvs) {
if (Function *Fun = dyn_cast<Function>(GV)) {
if (!is_inline || Fun != F)
printFunctionHead(Fun);
}
}
// Print the global variable declarations for any variables encountered
nl(Out) << "// Global Variable Declarations"; nl(Out);
2014-05-09 02:40:06 +08:00
for (auto *GV : gvs) {
if (GlobalVariable *F = dyn_cast<GlobalVariable>(GV))
printVariableHead(F);
}
// Print the constants found
nl(Out) << "// Constant Definitions"; nl(Out);
2014-05-09 02:40:06 +08:00
for (const auto *C : consts) {
printConstant(C);
}
// Process the global variables definitions now that all the constants have
// been emitted. These definitions just couple the gvars with their constant
// initializers.
if (GenerationType != GenFunction) {
nl(Out) << "// Global Variable Definitions"; nl(Out);
for (auto *GV : gvs) {
2014-05-09 02:40:06 +08:00
if (GlobalVariable *Var = dyn_cast<GlobalVariable>(GV))
printVariableBody(Var);
}
}
}
void CppWriter::printFunctionHead(const Function* F) {
nl(Out) << "Function* " << getCppName(F);
Out << " = mod->getFunction(\"";
printEscapedString(F->getName());
Out << "\");";
nl(Out) << "if (!" << getCppName(F) << ") {";
nl(Out) << getCppName(F);
Out<< " = Function::Create(";
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 (F->getDLLStorageClass() != GlobalValue::DefaultStorageClass) {
printCppName(F);
Out << "->setDLLStorageClass(";
printDLLStorageClassType(F->getDLLStorageClass());
Out << ");";
nl(Out);
}
if (F->hasGC()) {
printCppName(F);
Out << "->setGC(\"" << F->getGC() << "\");";
nl(Out);
}
Out << "}";
nl(Out);
printAttributes(F->getAttributes(), getCppName(F));
printCppName(F);
Out << "->setAttributes(" << 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 (const Argument &AI : F->args()) {
Out << "Value* " << getCppName(&AI) << " = args++;";
nl(Out);
if (AI.hasName()) {
Out << getCppName(&AI) << "->setName(\"";
printEscapedString(AI.getName());
Out << "\");";
nl(Out);
}
}
}
// Create all the basic blocks
nl(Out);
for (const BasicBlock &BI : *F) {
std::string bbname(getCppName(&BI));
Out << "BasicBlock* " << bbname <<
" = BasicBlock::Create(mod->getContext(), \"";
if (BI.hasName())
printEscapedString(BI.getName());
Out << "\"," << getCppName(BI.getParent()) << ",0);";
nl(Out);
}
// Output all of its basic blocks... for the function
for (const BasicBlock &BI : *F) {
std::string bbname(getCppName(&BI));
nl(Out) << "// Block " << BI.getName() << " (" << bbname << ")";
nl(Out);
// Output all of the instructions in the basic block...
for (const Instruction &I : BI)
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->front()) << ";";
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 (const Function &I : *TheModule)
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 (const GlobalVariable &I : TheModule->globals())
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 (const GlobalVariable &I : TheModule->globals())
printVariableBody(&I);
// Finally, we can safely put out all of the function bodies.
nl(Out) << "// Function Definitions"; nl(Out);
for (const Function &I : *TheModule) {
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/Pass.h>\n";
Out << "#include <llvm/ADT/SmallVector.h>\n";
Out << "#include <llvm/Analysis/Verifier.h>\n";
Out << "#include <llvm/IR/BasicBlock.h>\n";
Out << "#include <llvm/IR/CallingConv.h>\n";
Out << "#include <llvm/IR/Constants.h>\n";
Out << "#include <llvm/IR/DerivedTypes.h>\n";
Out << "#include <llvm/IR/Function.h>\n";
Out << "#include <llvm/IR/GlobalVariable.h>\n";
Out << "#include <llvm/IR/IRPrintingPasses.h>\n";
Out << "#include <llvm/IR/InlineAsm.h>\n";
Out << "#include <llvm/IR/Instructions.h>\n";
Out << "#include <llvm/IR/LLVMContext.h>\n";
Out << "#include <llvm/IR/LegacyPassManager.h>\n";
Out << "#include <llvm/IR/Module.h>\n";
Out << "#include <llvm/Support/FormattedStream.h>\n";
Out << "#include <llvm/Support/MathExtras.h>\n";
Out << "#include <algorithm>\n";
Out << "using namespace llvm;\n\n";
Out << "static LLVMContext TheContext;\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 << " PassManager PM;\n";
Out << " PM.add(createPrintModulePass(&outs()));\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(\"";
printEscapedString(mName);
Out << "\", TheContext);";
if (!TheModule->getTargetTriple().empty()) {
nl(Out) << "mod->setDataLayout(\"" << TheModule->getDataLayoutStr()
<< "\");";
}
if (!TheModule->getTargetTriple().empty()) {
nl(Out) << "mod->setTargetTriple(\"" << TheModule->getTargetTriple()
<< "\");";
}
if (!TheModule->getModuleInlineAsm().empty()) {
nl(Out) << "mod->setModuleInlineAsm(\"";
printEscapedString(TheModule->getModuleInlineAsm());
Out << "\");";
}
nl(Out);
printModuleBody();
nl(Out) << "return mod;";
nl(Out,-1) << "}";
nl(Out);
}
void CppWriter::printContents(const std::string& fname,
const std::string& mName) {
Out << "\nModule* " << fname << "(Module *mod) {\n";
Out << "\nmod->setModuleIdentifier(\"";
printEscapedString(mName);
Out << "\");\n";
printModuleBody();
Out << "\nreturn mod;\n";
Out << "\n}\n";
}
void CppWriter::printFunction(const std::string& fname,
const std::string& funcName) {
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,
const std::string& varName) {
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,
const std::string &typeName) {
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";
}
bool CppWriter::runOnModule(Module &M) {
TheModule = &M;
// Emit a header
Out << "// 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 (M.getModuleIdentifier() == "-")
tgtname = "<stdin>";
else
tgtname = M.getModuleIdentifier();
}
} else if (tgtname == "!bad!")
error("You must use the -for option with -gen-{function,variable,type}");
switch (WhatToGenerate(GenerationType)) {
case GenProgram:
if (fname.empty())
fname = "makeLLVMModule";
printProgram(fname,tgtname);
break;
case GenModule:
if (fname.empty())
fname = "makeLLVMModule";
printModule(fname,tgtname);
break;
case GenContents:
if (fname.empty())
fname = "makeLLVMModuleContents";
printContents(fname,tgtname);
break;
case GenFunction:
if (fname.empty())
fname = "makeLLVMFunction";
printFunction(fname,tgtname);
break;
case GenFunctions:
printFunctions();
break;
case GenInline:
if (fname.empty())
fname = "makeLLVMInline";
printInline(fname,tgtname);
break;
case GenVariable:
if (fname.empty())
fname = "makeLLVMVariable";
printVariable(fname,tgtname);
break;
case GenType:
if (fname.empty())
fname = "makeLLVMType";
printType(fname,tgtname);
break;
}
return false;
}
char CppWriter::ID = 0;
//===----------------------------------------------------------------------===//
// External Interface declaration
//===----------------------------------------------------------------------===//
bool CPPTargetMachine::addPassesToEmitFile(
PassManagerBase &PM, raw_pwrite_stream &o, CodeGenFileType FileType,
bool DisableVerify, AnalysisID StartBefore, AnalysisID StartAfter,
AnalysisID StopAfter, MachineFunctionInitializer *MFInitializer) {
if (FileType != TargetMachine::CGFT_AssemblyFile)
return true;
auto FOut = llvm::make_unique<formatted_raw_ostream>(o);
PM.add(new CppWriter(std::move(FOut)));
return false;
}