2008-04-24 06:29:24 +08:00
|
|
|
//===-- 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"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2015-04-10 05:06:08 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Config/config.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#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"
|
2015-02-13 18:01:29 +08:00
|
|
|
#include "llvm/IR/LegacyPassManager.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Module.h"
|
2011-07-15 07:50:31 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2011-07-11 11:57:24 +08:00
|
|
|
#include "llvm/MC/MCInstrInfo.h"
|
2011-07-09 13:47:46 +08:00
|
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Pass.h"
|
2008-04-24 06:29:24 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2009-07-09 04:55:50 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-07-15 04:18:05 +08:00
|
|
|
#include "llvm/Support/FormattedStream.h"
|
2011-08-25 02:08:43 +08:00
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
2008-04-24 06:29:24 +08:00
|
|
|
#include <algorithm>
|
2013-10-12 08:55:57 +08:00
|
|
|
#include <cctype>
|
2012-03-23 19:35:30 +08:00
|
|
|
#include <cstdio>
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
#include <map>
|
2012-03-23 19:35:30 +08:00
|
|
|
#include <set>
|
2008-04-24 06:29:24 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
static cl::opt<std::string>
|
2008-04-24 06:37:03 +08:00
|
|
|
FuncName("cppfname", cl::desc("Specify the name of the generated function"),
|
2008-04-24 06:29:24 +08:00
|
|
|
cl::value_desc("function name"));
|
|
|
|
|
|
|
|
enum WhatToGenerate {
|
|
|
|
GenProgram,
|
|
|
|
GenModule,
|
|
|
|
GenContents,
|
|
|
|
GenFunction,
|
|
|
|
GenFunctions,
|
|
|
|
GenInline,
|
|
|
|
GenVariable,
|
|
|
|
GenType
|
|
|
|
};
|
|
|
|
|
2008-04-24 06:37:03 +08:00
|
|
|
static cl::opt<WhatToGenerate> GenerationType("cppgen", cl::Optional,
|
2008-04-24 06:29:24 +08:00
|
|
|
cl::desc("Choose what kind of output to generate"),
|
|
|
|
cl::init(GenProgram),
|
|
|
|
cl::values(
|
2008-04-24 06:37:03 +08:00
|
|
|
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"),
|
2008-04-24 06:29:24 +08:00
|
|
|
clEnumValEnd
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2008-04-24 06:37:03 +08:00
|
|
|
static cl::opt<std::string> NameToGenerate("cppfor", cl::Optional,
|
2008-04-24 06:29:24 +08:00
|
|
|
cl::desc("Specify the name of the thing to generate"),
|
|
|
|
cl::init("!bad!"));
|
|
|
|
|
2009-07-25 14:49:55 +08:00
|
|
|
extern "C" void LLVMInitializeCppBackendTarget() {
|
|
|
|
// Register the target.
|
2009-08-04 12:02:45 +08:00
|
|
|
RegisterTargetMachine<CPPTargetMachine> X(TheCppBackendTarget);
|
2011-07-09 13:47:46 +08:00
|
|
|
}
|
|
|
|
|
2008-05-13 08:00:25 +08:00
|
|
|
namespace {
|
2011-07-18 12:54:35 +08:00
|
|
|
typedef std::vector<Type*> TypeList;
|
|
|
|
typedef std::map<Type*,std::string> TypeMap;
|
2008-04-24 06:29:24 +08:00
|
|
|
typedef std::map<const Value*,std::string> ValueMap;
|
|
|
|
typedef std::set<std::string> NameSet;
|
2011-07-18 12:54:35 +08:00
|
|
|
typedef std::set<Type*> TypeSet;
|
2008-04-24 06:29:24 +08:00
|
|
|
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 {
|
2015-04-10 05:06:08 +08:00
|
|
|
std::unique_ptr<formatted_raw_ostream> OutOwner;
|
2009-07-15 04:18:05 +08:00
|
|
|
formatted_raw_ostream &Out;
|
2008-04-24 06:29:24 +08:00
|
|
|
const Module *TheModule;
|
|
|
|
uint64_t uniqueNum;
|
|
|
|
TypeMap TypeNames;
|
|
|
|
ValueMap ValueNames;
|
|
|
|
NameSet UsedNames;
|
|
|
|
TypeSet DefinedTypes;
|
|
|
|
ValueSet DefinedValues;
|
|
|
|
ForwardRefMap ForwardRefs;
|
|
|
|
bool is_inline;
|
2010-06-22 07:14:47 +08:00
|
|
|
unsigned indent_level;
|
2008-04-24 06:29:24 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
static char ID;
|
2015-04-10 05:06:08 +08:00
|
|
|
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) {}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2014-04-29 15:58:41 +08:00
|
|
|
const char *getPassName() const override { return "C++ backend"; }
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2014-04-29 15:58:41 +08:00
|
|
|
bool runOnModule(Module &M) override;
|
2008-04-24 06:29:24 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2010-06-22 07:14:47 +08:00
|
|
|
|
|
|
|
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--; }
|
|
|
|
|
2008-04-24 06:29:24 +08:00
|
|
|
private:
|
|
|
|
void printLinkageType(GlobalValue::LinkageTypes LT);
|
|
|
|
void printVisibilityType(GlobalValue::VisibilityTypes VisTypes);
|
2014-01-14 23:22:47 +08:00
|
|
|
void printDLLStorageClassType(GlobalValue::DLLStorageClassTypes DSCType);
|
2012-06-23 19:37:03 +08:00
|
|
|
void printThreadLocalMode(GlobalVariable::ThreadLocalMode TLM);
|
2009-09-02 16:44:58 +08:00
|
|
|
void printCallingConv(CallingConv::ID cc);
|
2008-04-24 06:29:24 +08:00
|
|
|
void printEscapedString(const std::string& str);
|
|
|
|
void printCFP(const ConstantFP* CFP);
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
std::string getCppName(Type* val);
|
|
|
|
inline void printCppName(Type* val);
|
2008-04-24 06:29:24 +08:00
|
|
|
|
|
|
|
std::string getCppName(const Value* val);
|
|
|
|
inline void printCppName(const Value* val);
|
|
|
|
|
2012-12-08 07:16:57 +08:00
|
|
|
void printAttributes(const AttributeSet &PAL, const std::string &name);
|
2011-07-18 12:54:35 +08:00
|
|
|
void printType(Type* Ty);
|
2008-04-24 06:29:24 +08:00
|
|
|
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);
|
2011-09-30 04:21:17 +08:00
|
|
|
std::string getOpName(const Value*);
|
2008-04-24 06:29:24 +08:00
|
|
|
|
|
|
|
void printModuleBody();
|
|
|
|
};
|
2010-06-22 07:12:56 +08:00
|
|
|
} // end anonymous namespace.
|
|
|
|
|
2010-06-22 07:14:47 +08:00
|
|
|
formatted_raw_ostream &CppWriter::nl(formatted_raw_ostream &Out, int delta) {
|
|
|
|
Out << '\n';
|
2010-06-22 07:12:56 +08:00
|
|
|
if (delta >= 0 || indent_level >= unsigned(-delta))
|
|
|
|
indent_level += delta;
|
2010-06-22 07:14:47 +08:00
|
|
|
Out.indent(indent_level);
|
2010-06-22 07:12:56 +08:00
|
|
|
return Out;
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
static inline void sanitize(std::string &str) {
|
|
|
|
for (size_t i = 0; i < str.length(); ++i)
|
|
|
|
if (!isalnum(str[i]) && str[i] != '_')
|
|
|
|
str[i] = '_';
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
static std::string getTypePrefix(Type *Ty) {
|
2010-06-22 07:12:56 +08:00
|
|
|
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_";
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
void CppWriter::error(const std::string& msg) {
|
|
|
|
report_fatal_error(msg);
|
|
|
|
}
|
|
|
|
|
2012-03-23 19:26:29 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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(";
|
2008-04-24 06:29:24 +08:00
|
|
|
#if HAVE_PRINTF_A
|
2010-06-22 07:12:56 +08:00
|
|
|
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 {
|
2008-04-24 06:29:24 +08:00
|
|
|
#endif
|
2010-06-22 07:12:56 +08:00
|
|
|
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;
|
2008-04-24 06:29:24 +08:00
|
|
|
else
|
2010-06-22 07:12:56 +08:00
|
|
|
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 << ")";
|
2008-04-24 06:29:24 +08:00
|
|
|
#if HAVE_PRINTF_A
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
#endif
|
2010-06-22 07:12:56 +08:00
|
|
|
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;
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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;
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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;
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2014-01-14 23:22:47 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-23 19:37:03 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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'));
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
std::string CppWriter::getCppName(Type* Ty) {
|
2013-12-08 03:34:20 +08:00
|
|
|
switch (Ty->getTypeID()) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
case Type::VoidTyID:
|
2010-06-22 07:12:56 +08:00
|
|
|
return "Type::getVoidTy(mod->getContext())";
|
2013-12-08 03:34:20 +08:00
|
|
|
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())";
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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
|
2014-04-25 13:30:21 +08:00
|
|
|
const char* prefix = nullptr;
|
2010-06-22 07:12:56 +08:00
|
|
|
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
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// See if the type has a name in the symboltable and build accordingly
|
|
|
|
std::string name;
|
2011-07-18 12:54:35 +08:00
|
|
|
if (StructType *STy = dyn_cast<StructType>(Ty))
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
if (STy->hasName())
|
|
|
|
name = STy->getName();
|
|
|
|
|
|
|
|
if (name.empty())
|
|
|
|
name = utostr(uniqueNum++);
|
|
|
|
|
|
|
|
name = std::string(prefix) + name;
|
2010-06-22 07:12:56 +08:00
|
|
|
sanitize(name);
|
|
|
|
|
|
|
|
// Save the name
|
|
|
|
return TypeNames[Ty] = name;
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
void CppWriter::printCppName(Type* Ty) {
|
2010-06-22 07:12:56 +08:00
|
|
|
printEscapedString(getCppName(Ty));
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
std::string CppWriter::getCppName(const Value* val) {
|
|
|
|
std::string name;
|
|
|
|
ValueMap::iterator I = ValueNames.find(val);
|
|
|
|
if (I != ValueNames.end() && I->first == val)
|
|
|
|
return I->second;
|
|
|
|
|
|
|
|
if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(val)) {
|
|
|
|
name = std::string("gvar_") +
|
|
|
|
getTypePrefix(GV->getType()->getElementType());
|
|
|
|
} else if (isa<Function>(val)) {
|
|
|
|
name = std::string("func_");
|
|
|
|
} else if (const Constant* C = dyn_cast<Constant>(val)) {
|
|
|
|
name = std::string("const_") + getTypePrefix(C->getType());
|
|
|
|
} else if (const Argument* Arg = dyn_cast<Argument>(val)) {
|
|
|
|
if (is_inline) {
|
|
|
|
unsigned argNum = std::distance(Arg->getParent()->arg_begin(),
|
|
|
|
Function::const_arg_iterator(Arg)) + 1;
|
|
|
|
name = std::string("arg_") + utostr(argNum);
|
|
|
|
NameSet::iterator NI = UsedNames.find(name);
|
|
|
|
if (NI != UsedNames.end())
|
|
|
|
name += std::string("_") + utostr(uniqueNum++);
|
|
|
|
UsedNames.insert(name);
|
|
|
|
return ValueNames[val] = name;
|
2008-04-24 06:29:24 +08:00
|
|
|
} else {
|
|
|
|
name = getTypePrefix(val->getType());
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
} else {
|
|
|
|
name = getTypePrefix(val->getType());
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
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;
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
void CppWriter::printCppName(const Value* val) {
|
|
|
|
printEscapedString(getCppName(val));
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2012-12-08 07:16:57 +08:00
|
|
|
void CppWriter::printAttributes(const AttributeSet &PAL,
|
2010-06-22 07:12:56 +08:00
|
|
|
const std::string &name) {
|
2012-12-08 07:16:57 +08:00
|
|
|
Out << "AttributeSet " << name << "_PAL;";
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out);
|
|
|
|
if (!PAL.isEmpty()) {
|
|
|
|
Out << '{'; in(); nl(Out);
|
2013-01-27 09:22:51 +08:00
|
|
|
Out << "SmallVector<AttributeSet, 4> Attrs;"; nl(Out);
|
|
|
|
Out << "AttributeSet PAS;"; in(); nl(Out);
|
2010-06-22 07:12:56 +08:00
|
|
|
for (unsigned i = 0; i < PAL.getNumSlots(); ++i) {
|
2013-01-26 05:46:52 +08:00
|
|
|
unsigned index = PAL.getSlotIndex(i);
|
2013-01-26 07:09:36 +08:00
|
|
|
AttrBuilder attrs(PAL.getSlotAttributes(i), index);
|
2013-01-27 09:22:51 +08:00
|
|
|
Out << "{"; in(); nl(Out);
|
|
|
|
Out << "AttrBuilder B;"; nl(Out);
|
2012-10-10 15:36:45 +08:00
|
|
|
|
2013-01-27 09:22:51 +08:00
|
|
|
#define HANDLE_ATTR(X) \
|
|
|
|
if (attrs.contains(Attribute::X)) { \
|
|
|
|
Out << "B.addAttribute(Attribute::" #X ");"; nl(Out); \
|
|
|
|
attrs.removeAttribute(Attribute::X); \
|
|
|
|
}
|
2012-10-10 15:36:45 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
HANDLE_ATTR(SExt);
|
|
|
|
HANDLE_ATTR(ZExt);
|
|
|
|
HANDLE_ATTR(NoReturn);
|
|
|
|
HANDLE_ATTR(InReg);
|
|
|
|
HANDLE_ATTR(StructRet);
|
|
|
|
HANDLE_ATTR(NoUnwind);
|
|
|
|
HANDLE_ATTR(NoAlias);
|
|
|
|
HANDLE_ATTR(ByVal);
|
2013-12-19 10:14:12 +08:00
|
|
|
HANDLE_ATTR(InAlloca);
|
2010-06-22 07:12:56 +08:00
|
|
|
HANDLE_ATTR(Nest);
|
|
|
|
HANDLE_ATTR(ReadNone);
|
|
|
|
HANDLE_ATTR(ReadOnly);
|
|
|
|
HANDLE_ATTR(NoInline);
|
|
|
|
HANDLE_ATTR(AlwaysInline);
|
2013-08-23 19:53:55 +08:00
|
|
|
HANDLE_ATTR(OptimizeNone);
|
2010-06-22 07:12:56 +08:00
|
|
|
HANDLE_ATTR(OptimizeForSize);
|
|
|
|
HANDLE_ATTR(StackProtect);
|
|
|
|
HANDLE_ATTR(StackProtectReq);
|
2013-01-23 14:41:41 +08:00
|
|
|
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);
|
2010-06-22 07:12:56 +08:00
|
|
|
HANDLE_ATTR(NoCapture);
|
2010-07-17 02:47:20 +08:00
|
|
|
HANDLE_ATTR(NoRedZone);
|
|
|
|
HANDLE_ATTR(NoImplicitFloat);
|
|
|
|
HANDLE_ATTR(Naked);
|
|
|
|
HANDLE_ATTR(InlineHint);
|
2011-10-03 22:45:37 +08:00
|
|
|
HANDLE_ATTR(ReturnsTwice);
|
2011-08-09 08:47:30 +08:00
|
|
|
HANDLE_ATTR(UWTable);
|
|
|
|
HANDLE_ATTR(NonLazyBind);
|
2012-10-31 00:32:52 +08:00
|
|
|
HANDLE_ATTR(MinSize);
|
2009-01-13 15:22:22 +08:00
|
|
|
#undef HANDLE_ATTR
|
2013-01-27 09:22:51 +08:00
|
|
|
|
|
|
|
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);
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
2013-01-27 09:22:51 +08:00
|
|
|
Out << "Attrs.push_back(PAS);"; nl(Out);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2012-12-08 07:16:57 +08:00
|
|
|
Out << name << "_PAL = AttributeSet::get(mod->getContext(), Attrs);";
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out);
|
|
|
|
out(); nl(Out);
|
|
|
|
Out << '}'; nl(Out);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
void CppWriter::printType(Type* Ty) {
|
2010-06-22 07:12:56 +08:00
|
|
|
// We don't print definitions for primitive types
|
2013-12-08 03:34:20 +08:00
|
|
|
if (Ty->isFloatingPointTy() || Ty->isX86_MMXTy() || Ty->isIntegerTy() ||
|
|
|
|
Ty->isLabelTy() || Ty->isMetadataTy() || Ty->isVoidTy())
|
2011-07-15 05:04:35 +08:00
|
|
|
return;
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// If we already defined this type, we don't need to define it again.
|
|
|
|
if (DefinedTypes.find(Ty) != DefinedTypes.end())
|
2011-07-15 05:04:35 +08:00
|
|
|
return;
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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: {
|
2011-07-18 12:54:35 +08:00
|
|
|
FunctionType* FT = cast<FunctionType>(Ty);
|
2011-07-15 05:04:35 +08:00
|
|
|
Out << "std::vector<Type*>" << typeName << "_args;";
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out);
|
|
|
|
FunctionType::param_iterator PI = FT->param_begin();
|
|
|
|
FunctionType::param_iterator PE = FT->param_end();
|
|
|
|
for (; PI != PE; ++PI) {
|
2011-07-18 12:54:35 +08:00
|
|
|
Type* argTy = static_cast<Type*>(*PI);
|
2011-07-15 05:04:35 +08:00
|
|
|
printType(argTy);
|
2010-06-22 07:12:56 +08:00
|
|
|
std::string argName(getCppName(argTy));
|
|
|
|
Out << typeName << "_args.push_back(" << argName;
|
|
|
|
Out << ");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2011-07-15 05:04:35 +08:00
|
|
|
printType(FT->getReturnType());
|
2010-06-22 07:12:56 +08:00
|
|
|
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: {
|
2011-07-18 12:54:35 +08:00
|
|
|
StructType* ST = cast<StructType>(Ty);
|
2011-08-13 02:07:07 +08:00
|
|
|
if (!ST->isLiteral()) {
|
2011-10-08 19:56:36 +08:00
|
|
|
Out << "StructType *" << typeName << " = mod->getTypeByName(\"";
|
|
|
|
printEscapedString(ST->getName());
|
|
|
|
Out << "\");";
|
|
|
|
nl(Out);
|
|
|
|
Out << "if (!" << typeName << ") {";
|
|
|
|
nl(Out);
|
|
|
|
Out << typeName << " = ";
|
2011-08-13 02:07:07 +08:00
|
|
|
Out << "StructType::create(mod->getContext(), \"";
|
2011-07-15 05:04:35 +08:00
|
|
|
printEscapedString(ST->getName());
|
|
|
|
Out << "\");";
|
|
|
|
nl(Out);
|
2011-10-08 19:56:36 +08:00
|
|
|
Out << "}";
|
|
|
|
nl(Out);
|
2011-07-15 05:04:35 +08:00
|
|
|
// Indicate that this type is now defined.
|
|
|
|
DefinedTypes.insert(Ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << "std::vector<Type*>" << typeName << "_fields;";
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out);
|
|
|
|
StructType::element_iterator EI = ST->element_begin();
|
|
|
|
StructType::element_iterator EE = ST->element_end();
|
|
|
|
for (; EI != EE; ++EI) {
|
2011-07-18 12:54:35 +08:00
|
|
|
Type* fieldTy = static_cast<Type*>(*EI);
|
2011-07-15 05:04:35 +08:00
|
|
|
printType(fieldTy);
|
2010-06-22 07:12:56 +08:00
|
|
|
std::string fieldName(getCppName(fieldTy));
|
|
|
|
Out << typeName << "_fields.push_back(" << fieldName;
|
|
|
|
Out << ");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2011-07-15 05:04:35 +08:00
|
|
|
|
2011-08-13 02:07:07 +08:00
|
|
|
if (ST->isLiteral()) {
|
2011-07-15 05:04:35 +08:00
|
|
|
Out << "StructType *" << typeName << " = ";
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
Out << "StructType::get(" << "mod->getContext(), ";
|
|
|
|
} else {
|
2011-10-08 19:56:36 +08:00
|
|
|
Out << "if (" << typeName << "->isOpaque()) {";
|
|
|
|
nl(Out);
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
Out << typeName << "->setBody(";
|
|
|
|
}
|
2011-07-15 05:04:35 +08:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
Out << typeName << "_fields, /*isPacked=*/"
|
2010-06-22 07:12:56 +08:00
|
|
|
<< (ST->isPacked() ? "true" : "false") << ");";
|
|
|
|
nl(Out);
|
2011-10-08 19:56:36 +08:00
|
|
|
if (!ST->isLiteral()) {
|
|
|
|
Out << "}";
|
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Type::ArrayTyID: {
|
2011-07-18 12:54:35 +08:00
|
|
|
ArrayType* AT = cast<ArrayType>(Ty);
|
|
|
|
Type* ET = AT->getElementType();
|
2011-07-15 05:04:35 +08:00
|
|
|
printType(ET);
|
|
|
|
if (DefinedTypes.find(Ty) == DefinedTypes.end()) {
|
|
|
|
std::string elemName(getCppName(ET));
|
|
|
|
Out << "ArrayType* " << typeName << " = ArrayType::get("
|
2015-05-28 19:24:24 +08:00
|
|
|
<< elemName << ", " << AT->getNumElements() << ");";
|
2011-07-15 05:04:35 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Type::PointerTyID: {
|
2011-07-18 12:54:35 +08:00
|
|
|
PointerType* PT = cast<PointerType>(Ty);
|
|
|
|
Type* ET = PT->getElementType();
|
2011-07-15 05:04:35 +08:00
|
|
|
printType(ET);
|
|
|
|
if (DefinedTypes.find(Ty) == DefinedTypes.end()) {
|
|
|
|
std::string elemName(getCppName(ET));
|
|
|
|
Out << "PointerType* " << typeName << " = PointerType::get("
|
2015-05-28 19:24:24 +08:00
|
|
|
<< elemName << ", " << PT->getAddressSpace() << ");";
|
2011-07-15 05:04:35 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Type::VectorTyID: {
|
2011-07-18 12:54:35 +08:00
|
|
|
VectorType* PT = cast<VectorType>(Ty);
|
|
|
|
Type* ET = PT->getElementType();
|
2011-07-15 05:04:35 +08:00
|
|
|
printType(ET);
|
|
|
|
if (DefinedTypes.find(Ty) == DefinedTypes.end()) {
|
|
|
|
std::string elemName(getCppName(ET));
|
|
|
|
Out << "VectorType* " << typeName << " = VectorType::get("
|
2015-05-28 19:24:24 +08:00
|
|
|
<< elemName << ", " << PT->getNumElements() << ");";
|
2011-07-15 05:04:35 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
error("Invalid TypeID");
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Indicate that this type is now defined.
|
|
|
|
DefinedTypes.insert(Ty);
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Finally, separate the type definition from other with a newline.
|
|
|
|
nl(Out);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CppWriter::printTypes(const Module* M) {
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
// Add all of the global variables to the value table.
|
2010-06-22 07:12:56 +08:00
|
|
|
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());
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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());
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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;
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
std::string constName(getCppName(CV));
|
|
|
|
std::string typeName(getCppName(CV->getType()));
|
2008-10-05 23:07:06 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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)) {
|
2012-02-05 10:29:43 +08:00
|
|
|
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)) << ");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2012-02-05 10:29:43 +08:00
|
|
|
Out << "Constant* " << constName << " = ConstantArray::get("
|
|
|
|
<< typeName << ", " << constName << "_elems);";
|
2010-06-22 07:12:56 +08:00
|
|
|
} 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);";
|
2012-02-05 22:16:09 +08:00
|
|
|
} else if (const ConstantVector *CVec = dyn_cast<ConstantVector>(CV)) {
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "std::vector<Constant*> " << constName << "_elems;";
|
|
|
|
nl(Out);
|
2012-02-05 22:16:09 +08:00
|
|
|
unsigned N = CVec->getNumOperands();
|
2010-06-22 07:12:56 +08:00
|
|
|
for (unsigned i = 0; i < N; ++i) {
|
2012-02-05 22:16:09 +08:00
|
|
|
printConstant(CVec->getOperand(i));
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << constName << "_elems.push_back("
|
2012-02-05 22:16:09 +08:00
|
|
|
<< getCppName(CVec->getOperand(i)) << ");";
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
|
|
|
Out << "Constant* " << constName << " = ConstantVector::get("
|
|
|
|
<< typeName << ", " << constName << "_elems);";
|
|
|
|
} else if (isa<UndefValue>(CV)) {
|
|
|
|
Out << "UndefValue* " << constName << " = UndefValue::get("
|
|
|
|
<< typeName << ");";
|
2012-01-24 22:17:05 +08:00
|
|
|
} else if (const ConstantDataSequential *CDS =
|
|
|
|
dyn_cast<ConstantDataSequential>(CV)) {
|
|
|
|
if (CDS->isString()) {
|
|
|
|
Out << "Constant *" << constName <<
|
|
|
|
" = ConstantDataArray::getString(mod->getContext(), \"";
|
2012-02-05 10:29:43 +08:00
|
|
|
StringRef Str = CDS->getAsString();
|
2012-01-24 22:17:05 +08:00
|
|
|
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);";
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
} 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)) << ");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
|
|
|
Out << "Constant* " << constName
|
|
|
|
<< " = ConstantExpr::getGetElementPtr("
|
|
|
|
<< getCppName(CE->getOperand(0)) << ", "
|
2011-07-22 04:59:21 +08:00
|
|
|
<< constName << "_indices);";
|
2010-06-22 07:12:56 +08:00
|
|
|
} 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");
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
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");
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
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;
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << getCppName(CE->getOperand(0));
|
|
|
|
for (unsigned i = 1; i < CE->getNumOperands(); ++i)
|
|
|
|
Out << ", " << getCppName(CE->getOperand(i));
|
|
|
|
Out << ");";
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:19:36 +08:00
|
|
|
} else if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) {
|
|
|
|
Out << "Constant* " << constName << " = ";
|
|
|
|
Out << "BlockAddress::get(" << getOpName(BA->getBasicBlock()) << ");";
|
2010-06-22 07:12:56 +08:00
|
|
|
} else {
|
|
|
|
error("Bad Constant");
|
|
|
|
Out << "Constant* " << constName << " = 0; ";
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
void CppWriter::printVariableUses(const GlobalVariable *GV) {
|
|
|
|
nl(Out) << "// Type Definitions";
|
|
|
|
nl(Out);
|
|
|
|
printType(GV->getType());
|
|
|
|
if (GV->hasInitializer()) {
|
2011-06-20 02:37:11 +08:00
|
|
|
const Constant *Init = GV->getInitializer();
|
2010-06-22 07:12:56 +08:00
|
|
|
printType(Init->getType());
|
2011-06-20 02:37:11 +08:00
|
|
|
if (const Function *F = dyn_cast<Function>(Init)) {
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out)<< "/ Function Declarations"; nl(Out);
|
|
|
|
printFunctionHead(F);
|
2011-06-20 02:37:11 +08:00
|
|
|
} else if (const GlobalVariable* gv = dyn_cast<GlobalVariable>(Init)) {
|
2010-06-22 07:12:56 +08:00
|
|
|
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);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
void CppWriter::printVariableHead(const GlobalVariable *GV) {
|
|
|
|
nl(Out) << "GlobalVariable* " << getCppName(GV);
|
|
|
|
if (is_inline) {
|
|
|
|
Out << " = mod->getGlobalVariable(mod->getContext(), ";
|
2008-04-24 06:29:24 +08:00
|
|
|
printEscapedString(GV->getName());
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << ", " << getCppName(GV->getType()->getElementType()) << ",true)";
|
|
|
|
nl(Out) << "if (!" << getCppName(GV) << ") {";
|
|
|
|
in(); nl(Out) << getCppName(GV);
|
|
|
|
}
|
|
|
|
Out << " = new GlobalVariable(/*Module=*/*mod, ";
|
|
|
|
nl(Out) << "/*Type=*/";
|
|
|
|
printCppName(GV->getType()->getElementType());
|
|
|
|
Out << ",";
|
|
|
|
nl(Out) << "/*isConstant=*/" << (GV->isConstant()?"true":"false");
|
|
|
|
Out << ",";
|
|
|
|
nl(Out) << "/*Linkage=*/";
|
|
|
|
printLinkageType(GV->getLinkage());
|
|
|
|
Out << ",";
|
|
|
|
nl(Out) << "/*Initializer=*/0, ";
|
|
|
|
if (GV->hasInitializer()) {
|
|
|
|
Out << "// has initializer, specified below";
|
|
|
|
}
|
|
|
|
nl(Out) << "/*Name=*/\"";
|
|
|
|
printEscapedString(GV->getName());
|
|
|
|
Out << "\");";
|
|
|
|
nl(Out);
|
|
|
|
|
|
|
|
if (GV->hasSection()) {
|
|
|
|
printCppName(GV);
|
|
|
|
Out << "->setSection(\"";
|
|
|
|
printEscapedString(GV->getSection());
|
2009-07-11 00:42:19 +08:00
|
|
|
Out << "\");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
if (GV->getAlignment()) {
|
|
|
|
printCppName(GV);
|
2015-05-28 19:24:24 +08:00
|
|
|
Out << "->setAlignment(" << GV->getAlignment() << ");";
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
|
|
|
if (GV->getVisibility() != GlobalValue::DefaultVisibility) {
|
|
|
|
printCppName(GV);
|
|
|
|
Out << "->setVisibility(";
|
|
|
|
printVisibilityType(GV->getVisibility());
|
|
|
|
Out << ");";
|
|
|
|
nl(Out);
|
|
|
|
}
|
2014-01-14 23:22:47 +08:00
|
|
|
if (GV->getDLLStorageClass() != GlobalValue::DefaultStorageClass) {
|
|
|
|
printCppName(GV);
|
|
|
|
Out << "->setDLLStorageClass(";
|
|
|
|
printDLLStorageClassType(GV->getDLLStorageClass());
|
|
|
|
Out << ");";
|
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
if (GV->isThreadLocal()) {
|
|
|
|
printCppName(GV);
|
2012-06-23 19:37:03 +08:00
|
|
|
Out << "->setThreadLocalMode(";
|
|
|
|
printThreadLocalMode(GV->getThreadLocalMode());
|
|
|
|
Out << ");";
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
|
|
|
if (is_inline) {
|
|
|
|
out(); Out << "}"; nl(Out);
|
|
|
|
}
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
void CppWriter::printVariableBody(const GlobalVariable *GV) {
|
|
|
|
if (GV->hasInitializer()) {
|
|
|
|
printCppName(GV);
|
|
|
|
Out << "->setInitializer(";
|
|
|
|
Out << getCppName(GV->getInitializer()) << ");";
|
|
|
|
nl(Out);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2011-09-30 04:21:17 +08:00
|
|
|
std::string CppWriter::getOpName(const Value* V) {
|
2010-06-22 07:12:56 +08:00
|
|
|
if (!isa<Instruction>(V) || DefinedValues.find(V) != DefinedValues.end())
|
|
|
|
return getCppName(V);
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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;
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// This is a new forward reference. Generate a unique name for it
|
|
|
|
std::string result(std::string("fwdref_") + utostr(uniqueNum++));
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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;
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2011-11-01 07:59:22 +08:00
|
|
|
static StringRef ConvertAtomicOrdering(AtomicOrdering Ordering) {
|
|
|
|
switch (Ordering) {
|
|
|
|
case NotAtomic: return "NotAtomic";
|
|
|
|
case Unordered: return "Unordered";
|
|
|
|
case Monotonic: return "Monotonic";
|
|
|
|
case Acquire: return "Acquire";
|
|
|
|
case Release: return "Release";
|
|
|
|
case AcquireRelease: return "AcquireRelease";
|
|
|
|
case 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");
|
|
|
|
}
|
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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];
|
2010-06-22 07:19:36 +08:00
|
|
|
for (unsigned i = 0; i < Ops; i++)
|
2010-06-22 07:12:56 +08:00
|
|
|
opNames[i] = getOpName(I->getOperand(i));
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
switch (I->getOpcode()) {
|
|
|
|
default:
|
|
|
|
error("Invalid instruction");
|
|
|
|
break;
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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(" ;
|
2010-06-22 07:19:36 +08:00
|
|
|
if (br->getNumOperands() == 3) {
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << opNames[2] << ", "
|
|
|
|
<< opNames[1] << ", "
|
|
|
|
<< opNames[0] << ", ";
|
2008-06-09 22:09:13 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
} else if (br->getNumOperands() == 1) {
|
|
|
|
Out << opNames[0] << ", ";
|
|
|
|
} else {
|
|
|
|
error("Branch with 2 operands?");
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << bbname << ");";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Instruction::Switch: {
|
|
|
|
const SwitchInst *SI = cast<SwitchInst>(I);
|
|
|
|
Out << "SwitchInst* " << iName << " = SwitchInst::Create("
|
2011-09-30 04:21:17 +08:00
|
|
|
<< getOpName(SI->getCondition()) << ", "
|
|
|
|
<< getOpName(SI->getDefaultDest()) << ", "
|
2010-06-22 07:12:56 +08:00
|
|
|
<< SI->getNumCases() << ", " << bbname << ");";
|
|
|
|
nl(Out);
|
2012-03-11 14:09:17 +08:00
|
|
|
for (SwitchInst::ConstCaseIt i = SI->case_begin(), e = SI->case_end();
|
2012-03-08 15:06:20 +08:00
|
|
|
i != e; ++i) {
|
Revert patches to add case-range support for PR1255.
The work on this project was left in an unfinished and inconsistent state.
Hopefully someone will eventually get a chance to implement this feature, but
in the meantime, it is better to put things back the way the were. I have
left support in the bitcode reader to handle the case-range bitcode format,
so that we do not lose bitcode compatibility with the llvm 3.3 release.
This reverts the following commits: 155464, 156374, 156377, 156613, 156704,
156757, 156804 156808, 156985, 157046, 157112, 157183, 157315, 157384, 157575,
157576, 157586, 157612, 157810, 157814, 157815, 157880, 157881, 157882, 157884,
157887, 157901, 158979, 157987, 157989, 158986, 158997, 159076, 159101, 159100,
159200, 159201, 159207, 159527, 159532, 159540, 159583, 159618, 159658, 159659,
159660, 159661, 159703, 159704, 160076, 167356, 172025, 186736
llvm-svn: 190328
2013-09-10 03:14:35 +08:00
|
|
|
const ConstantInt* CaseVal = i.getCaseValue();
|
2012-03-08 15:06:20 +08:00
|
|
|
const BasicBlock *BB = i.getCaseSuccessor();
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << iName << "->addCase("
|
2011-09-30 04:21:17 +08:00
|
|
|
<< getOpName(CaseVal) << ", "
|
|
|
|
<< getOpName(BB) << ");";
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
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] << ");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-07-31 14:30:59 +08:00
|
|
|
case Instruction::Resume: {
|
2013-09-24 08:36:09 +08:00
|
|
|
Out << "ResumeInst::Create(" << opNames[0] << ", " << bbname << ");";
|
2011-07-31 14:30:59 +08:00
|
|
|
break;
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
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)) << ");";
|
2009-10-28 05:24:48 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
// FIXME: This shouldn't use magic numbers -3, -2, and -1.
|
|
|
|
Out << "InvokeInst *" << iName << " = InvokeInst::Create("
|
2013-09-24 08:36:09 +08:00
|
|
|
<< getOpName(inv->getCalledValue()) << ", "
|
2010-06-22 07:12:56 +08:00
|
|
|
<< getOpName(inv->getNormalDest()) << ", "
|
|
|
|
<< getOpName(inv->getUnwindDest()) << ", "
|
2011-09-06 02:50:59 +08:00
|
|
|
<< iName << "_params, \"";
|
2010-06-22 07:12:56 +08:00
|
|
|
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: {
|
2010-06-22 07:12:56 +08:00
|
|
|
const LoadInst* load = cast<LoadInst>(I);
|
|
|
|
Out << "LoadInst* " << iName << " = new LoadInst("
|
|
|
|
<< opNames[0] << ", \"";
|
|
|
|
printEscapedString(load->getName());
|
|
|
|
Out << "\", " << (load->isVolatile() ? "true" : "false" )
|
|
|
|
<< ", " << bbname << ");";
|
2011-11-01 07:59:22 +08:00
|
|
|
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 << ");";
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Instruction::Store: {
|
|
|
|
const StoreInst* store = cast<StoreInst>(I);
|
2011-11-01 07:59:22 +08:00
|
|
|
Out << "StoreInst* " << iName << " = new StoreInst("
|
2010-06-22 07:12:56 +08:00
|
|
|
<< opNames[0] << ", "
|
|
|
|
<< opNames[1] << ", "
|
|
|
|
<< (store->isVolatile() ? "true" : "false")
|
|
|
|
<< ", " << bbname << ");";
|
2011-11-01 07:59:22 +08:00
|
|
|
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 << ");";
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Instruction::GetElementPtr: {
|
|
|
|
const GetElementPtrInst* gep = cast<GetElementPtrInst>(I);
|
|
|
|
if (gep->getNumOperands() <= 2) {
|
|
|
|
Out << "GetElementPtrInst* " << iName << " = GetElementPtrInst::Create("
|
|
|
|
<< opNames[0];
|
|
|
|
if (gep->getNumOperands() == 2)
|
|
|
|
Out << ", " << opNames[1];
|
|
|
|
} else {
|
|
|
|
Out << "std::vector<Value*> " << iName << "_indices;";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
2010-06-22 07:12:56 +08:00
|
|
|
for (unsigned i = 1; i < gep->getNumOperands(); ++i ) {
|
|
|
|
Out << iName << "_indices.push_back("
|
|
|
|
<< opNames[i] << ");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "Instruction* " << iName << " = GetElementPtrInst::Create("
|
2011-07-27 04:52:25 +08:00
|
|
|
<< opNames[0] << ", " << iName << "_indices";
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
|
|
|
Out << ", \"";
|
|
|
|
printEscapedString(gep->getName());
|
|
|
|
Out << "\", " << bbname << ");";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Instruction::PHI: {
|
|
|
|
const PHINode* phi = cast<PHINode>(I);
|
|
|
|
|
|
|
|
Out << "PHINode* " << iName << " = PHINode::Create("
|
2011-04-11 01:39:40 +08:00
|
|
|
<< getCppName(phi->getType()) << ", "
|
2011-03-30 19:28:46 +08:00
|
|
|
<< phi->getNumIncomingValues() << ", \"";
|
2010-06-22 07:12:56 +08:00
|
|
|
printEscapedString(phi->getName());
|
|
|
|
Out << "\", " << bbname << ");";
|
|
|
|
nl(Out);
|
2011-06-20 22:18:48 +08:00
|
|
|
for (unsigned i = 0; i < phi->getNumIncomingValues(); ++i) {
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << iName << "->addIncoming("
|
2011-06-20 22:18:48 +08:00
|
|
|
<< opNames[PHINode::getOperandNumForIncomingValue(i)] << ", "
|
2011-06-23 17:09:15 +08:00
|
|
|
<< getOpName(phi->getIncomingBlock(i)) << ");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
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;
|
2012-02-07 10:50:20 +08:00
|
|
|
default: llvm_unreachable("Unreachable");
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
|
|
|
Out << "(" << opNames[0] << ", "
|
|
|
|
<< getCppName(cst->getType()) << ", \"";
|
|
|
|
printEscapedString(cst->getName());
|
|
|
|
Out << "\", " << bbname << ");";
|
|
|
|
break;
|
|
|
|
}
|
2010-06-26 20:17:21 +08:00
|
|
|
case Instruction::Call: {
|
2010-06-22 07:12:56 +08:00
|
|
|
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") << ");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-26 20:17:21 +08:00
|
|
|
if (call->getNumArgOperands() > 1) {
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "std::vector<Value*> " << iName << "_params;";
|
|
|
|
nl(Out);
|
2010-07-03 03:08:46 +08:00
|
|
|
for (unsigned i = 0; i < call->getNumArgOperands(); ++i) {
|
2010-07-13 23:31:36 +08:00
|
|
|
Out << iName << "_params.push_back(" << opNames[i] << ");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "CallInst* " << iName << " = CallInst::Create("
|
2010-07-22 18:37:47 +08:00
|
|
|
<< opNames[call->getNumArgOperands()] << ", "
|
2011-07-22 04:59:21 +08:00
|
|
|
<< iName << "_params, \"";
|
2010-06-26 20:17:21 +08:00
|
|
|
} else if (call->getNumArgOperands() == 1) {
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "CallInst* " << iName << " = CallInst::Create("
|
2010-07-13 23:31:36 +08:00
|
|
|
<< opNames[call->getNumArgOperands()] << ", " << opNames[0] << ", \"";
|
2010-06-22 07:12:56 +08:00
|
|
|
} else {
|
2010-07-13 23:31:36 +08:00
|
|
|
Out << "CallInst* " << iName << " = CallInst::Create("
|
|
|
|
<< opNames[call->getNumArgOperands()] << ", \"";
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
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");
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << ");";
|
2010-07-03 03:26:28 +08:00
|
|
|
nl(Out);
|
2010-06-22 07:12:56 +08:00
|
|
|
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] << ");";
|
2008-06-09 22:12:10 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "ExtractValueInst* " << getCppName(evi)
|
|
|
|
<< " = ExtractValueInst::Create(" << opNames[0]
|
|
|
|
<< ", "
|
2011-09-06 02:50:59 +08:00
|
|
|
<< iName << "_indices, \"";
|
2010-06-22 07:12:56 +08:00
|
|
|
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] << ");";
|
2008-06-09 22:12:10 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "InsertValueInst* " << getCppName(ivi)
|
|
|
|
<< " = InsertValueInst::Create(" << opNames[0]
|
|
|
|
<< ", " << opNames[1] << ", "
|
2011-09-06 02:50:59 +08:00
|
|
|
<< iName << "_indices, \"";
|
2010-06-22 07:12:56 +08:00
|
|
|
printEscapedString(ivi->getName());
|
|
|
|
Out << "\", " << bbname << ");";
|
|
|
|
break;
|
|
|
|
}
|
2011-11-01 07:59:22 +08:00
|
|
|
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(), "
|
2011-11-05 01:29:35 +08:00
|
|
|
<< Ordering << ", " << CrossThread << ", " << bbname
|
2011-11-01 07:59:22 +08:00
|
|
|
<< ");";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Instruction::AtomicCmpXchg: {
|
|
|
|
const AtomicCmpXchgInst *cxi = cast<AtomicCmpXchgInst>(I);
|
2014-03-11 18:48:52 +08:00
|
|
|
StringRef SuccessOrdering =
|
|
|
|
ConvertAtomicOrdering(cxi->getSuccessOrdering());
|
|
|
|
StringRef FailureOrdering =
|
|
|
|
ConvertAtomicOrdering(cxi->getFailureOrdering());
|
2011-11-01 07:59:22 +08:00
|
|
|
StringRef CrossThread = ConvertAtomicSynchScope(cxi->getSynchScope());
|
|
|
|
Out << "AtomicCmpXchgInst* " << iName
|
|
|
|
<< " = new AtomicCmpXchgInst("
|
|
|
|
<< opNames[0] << ", " << opNames[1] << ", " << opNames[2] << ", "
|
2014-03-11 18:48:52 +08:00
|
|
|
<< SuccessOrdering << ", " << FailureOrdering << ", "
|
|
|
|
<< CrossThread << ", " << bbname
|
2011-11-01 07:59:22 +08:00
|
|
|
<< ");";
|
|
|
|
nl(Out) << iName << "->setName(\"";
|
|
|
|
printEscapedString(cxi->getName());
|
|
|
|
Out << "\");";
|
2014-06-13 17:14:50 +08:00
|
|
|
nl(Out) << iName << "->setVolatile("
|
|
|
|
<< (cxi->isVolatile() ? "true" : "false") << ");";
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
nl(Out) << iName << "->setWeak("
|
|
|
|
<< (cxi->isWeak() ? "true" : "false") << ");";
|
2011-11-01 07:59:22 +08:00
|
|
|
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] << ", "
|
2011-11-05 01:29:35 +08:00
|
|
|
<< Ordering << ", " << CrossThread << ", " << bbname
|
2011-11-01 07:59:22 +08:00
|
|
|
<< ");";
|
|
|
|
nl(Out) << iName << "->setName(\"";
|
|
|
|
printEscapedString(rmwi->getName());
|
|
|
|
Out << "\");";
|
2014-06-13 17:14:50 +08:00
|
|
|
nl(Out) << iName << "->setVolatile("
|
|
|
|
<< (rmwi->isVolatile() ? "true" : "false") << ");";
|
2011-11-01 07:59:22 +08:00
|
|
|
break;
|
|
|
|
}
|
2013-09-24 08:36:09 +08:00
|
|
|
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;
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
DefinedValues.insert(I);
|
|
|
|
nl(Out);
|
|
|
|
delete [] opNames;
|
|
|
|
}
|
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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());
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Print the function's function type
|
|
|
|
printType(F->getFunctionType());
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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());
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Print type definitions for every type referenced by an instruction and
|
|
|
|
// make a note of any global values or constants that are referenced
|
|
|
|
SmallPtrSet<GlobalValue*,64> gvs;
|
|
|
|
SmallPtrSet<Constant*,64> consts;
|
|
|
|
for (Function::const_iterator BB = F->begin(), BE = F->end();
|
|
|
|
BB != BE; ++BB){
|
|
|
|
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
|
|
|
|
I != E; ++I) {
|
|
|
|
// Print the type of the instruction itself
|
|
|
|
printType(I->getType());
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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);
|
2010-11-29 02:00:53 +08:00
|
|
|
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)) {
|
2010-06-22 07:12:56 +08:00
|
|
|
consts.insert(C);
|
2015-06-26 04:51:38 +08:00
|
|
|
for (Value* operand : C->operands()) {
|
2010-11-29 02:00:53 +08:00
|
|
|
// 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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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)) {
|
2010-06-22 07:12:56 +08:00
|
|
|
if (!is_inline || Fun != F)
|
|
|
|
printFunctionHead(Fun);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// 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))
|
2010-06-22 07:12:56 +08:00
|
|
|
printVariableHead(F);
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-11-29 02:00:53 +08:00
|
|
|
// Print the constants found
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out) << "// Constant Definitions"; nl(Out);
|
2014-05-09 02:40:06 +08:00
|
|
|
for (const auto *C : consts) {
|
|
|
|
printConstant(C);
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Process the global variables definitions now that all the constants have
|
|
|
|
// been emitted. These definitions just couple the gvars with their constant
|
|
|
|
// initializers.
|
2010-11-29 02:00:53 +08:00
|
|
|
if (GenerationType != GenFunction) {
|
|
|
|
nl(Out) << "// Global Variable Definitions"; nl(Out);
|
2015-04-16 20:43:07 +08:00
|
|
|
for (auto *GV : gvs) {
|
2014-05-09 02:40:06 +08:00
|
|
|
if (GlobalVariable *Var = dyn_cast<GlobalVariable>(GV))
|
|
|
|
printVariableBody(Var);
|
2010-11-29 02:00:53 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
void CppWriter::printFunctionHead(const Function* F) {
|
|
|
|
nl(Out) << "Function* " << getCppName(F);
|
2011-10-08 19:56:36 +08:00
|
|
|
Out << " = mod->getFunction(\"";
|
|
|
|
printEscapedString(F->getName());
|
|
|
|
Out << "\");";
|
|
|
|
nl(Out) << "if (!" << getCppName(F) << ") {";
|
|
|
|
nl(Out) << getCppName(F);
|
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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) {
|
2008-04-24 06:29:24 +08:00
|
|
|
printCppName(F);
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "->setVisibility(";
|
|
|
|
printVisibilityType(F->getVisibility());
|
2008-04-24 06:29:24 +08:00
|
|
|
Out << ");";
|
|
|
|
nl(Out);
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2014-01-14 23:22:47 +08:00
|
|
|
if (F->getDLLStorageClass() != GlobalValue::DefaultStorageClass) {
|
|
|
|
printCppName(F);
|
|
|
|
Out << "->setDLLStorageClass(";
|
|
|
|
printDLLStorageClassType(F->getDLLStorageClass());
|
|
|
|
Out << ");";
|
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
if (F->hasGC()) {
|
2008-04-24 06:29:24 +08:00
|
|
|
printCppName(F);
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "->setGC(\"" << F->getGC() << "\");";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2011-10-08 19:56:36 +08:00
|
|
|
Out << "}";
|
|
|
|
nl(Out);
|
2010-06-22 07:12:56 +08:00
|
|
|
printAttributes(F->getAttributes(), getCppName(F));
|
|
|
|
printCppName(F);
|
|
|
|
Out << "->setAttributes(" << getCppName(F) << "_PAL);";
|
|
|
|
nl(Out);
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
void CppWriter::printFunctionBody(const Function *F) {
|
|
|
|
if (F->isDeclaration())
|
|
|
|
return; // external functions have no bodies.
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Clear the DefinedValues and ForwardRefs maps because we can't have
|
|
|
|
// cross-function forward refs
|
|
|
|
ForwardRefs.clear();
|
|
|
|
DefinedValues.clear();
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Create all the argument values
|
|
|
|
if (!is_inline) {
|
|
|
|
if (!F->arg_empty()) {
|
|
|
|
Out << "Function::arg_iterator args = " << getCppName(F)
|
|
|
|
<< "->arg_begin();";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
|
|
|
|
AI != AE; ++AI) {
|
|
|
|
Out << "Value* " << getCppName(AI) << " = args++;";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
2010-06-22 07:12:56 +08:00
|
|
|
if (AI->hasName()) {
|
2011-11-01 07:59:22 +08:00
|
|
|
Out << getCppName(AI) << "->setName(\"";
|
|
|
|
printEscapedString(AI->getName());
|
|
|
|
Out << "\");";
|
2010-06-22 07:12:56 +08:00
|
|
|
nl(Out);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Create all the basic blocks
|
|
|
|
nl(Out);
|
|
|
|
for (Function::const_iterator BI = F->begin(), BE = F->end();
|
|
|
|
BI != BE; ++BI) {
|
|
|
|
std::string bbname(getCppName(BI));
|
|
|
|
Out << "BasicBlock* " << bbname <<
|
|
|
|
" = BasicBlock::Create(mod->getContext(), \"";
|
|
|
|
if (BI->hasName())
|
|
|
|
printEscapedString(BI->getName());
|
|
|
|
Out << "\"," << getCppName(BI->getParent()) << ",0);";
|
|
|
|
nl(Out);
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Output all of its basic blocks... for the function
|
|
|
|
for (Function::const_iterator BI = F->begin(), BE = F->end();
|
|
|
|
BI != BE; ++BI) {
|
|
|
|
std::string bbname(getCppName(BI));
|
|
|
|
nl(Out) << "// Block " << BI->getName() << " (" << bbname << ")";
|
|
|
|
nl(Out);
|
|
|
|
|
|
|
|
// Output all of the instructions in the basic block...
|
|
|
|
for (BasicBlock::const_iterator I = BI->begin(), E = BI->end();
|
|
|
|
I != E; ++I) {
|
|
|
|
printInstruction(I,bbname);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Loop over the ForwardRefs and resolve them now that all instructions
|
|
|
|
// are generated.
|
|
|
|
if (!ForwardRefs.empty()) {
|
|
|
|
nl(Out) << "// Resolve Forward References";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
while (!ForwardRefs.empty()) {
|
|
|
|
ForwardRefMap::iterator I = ForwardRefs.begin();
|
|
|
|
Out << I->second << "->replaceAllUsesWith("
|
|
|
|
<< getCppName(I->first) << "); delete " << I->second << ";";
|
2008-04-24 06:29:24 +08:00
|
|
|
nl(Out);
|
2010-06-22 07:12:56 +08:00
|
|
|
ForwardRefs.erase(I);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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) {
|
2013-07-31 11:22:07 +08:00
|
|
|
Out << ", Value* arg_" << arg_count++;
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
|
|
|
Out << ") {";
|
|
|
|
nl(Out);
|
|
|
|
is_inline = true;
|
|
|
|
printFunctionUses(F);
|
|
|
|
printFunctionBody(F);
|
|
|
|
is_inline = false;
|
|
|
|
Out << "return " << getCppName(F->begin()) << ";";
|
|
|
|
nl(Out) << "}";
|
|
|
|
nl(Out);
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
void CppWriter::printModuleBody() {
|
|
|
|
// Print out all the type definitions
|
|
|
|
nl(Out) << "// Type Definitions"; nl(Out);
|
|
|
|
printTypes(TheModule);
|
|
|
|
|
|
|
|
// Functions can call each other and global variables can reference them so
|
|
|
|
// define all the functions first before emitting their function bodies.
|
|
|
|
nl(Out) << "// Function Declarations"; nl(Out);
|
|
|
|
for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
|
|
|
|
I != E; ++I)
|
|
|
|
printFunctionHead(I);
|
|
|
|
|
|
|
|
// Process the global variables declarations. We can't initialze them until
|
|
|
|
// after the constants are printed so just print a header for each global
|
|
|
|
nl(Out) << "// Global Variable Declarations\n"; nl(Out);
|
|
|
|
for (Module::const_global_iterator I = TheModule->global_begin(),
|
|
|
|
E = TheModule->global_end(); I != E; ++I) {
|
|
|
|
printVariableHead(I);
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Print out all the constants definitions. Constants don't recurse except
|
|
|
|
// through GlobalValues. All GlobalValues have been declared at this point
|
|
|
|
// so we can proceed to generate the constants.
|
|
|
|
nl(Out) << "// Constant Definitions"; nl(Out);
|
|
|
|
printConstants(TheModule);
|
|
|
|
|
|
|
|
// Process the global variables definitions now that all the constants have
|
|
|
|
// been emitted. These definitions just couple the gvars with their constant
|
|
|
|
// initializers.
|
|
|
|
nl(Out) << "// Global Variable Definitions"; nl(Out);
|
|
|
|
for (Module::const_global_iterator I = TheModule->global_begin(),
|
|
|
|
E = TheModule->global_end(); I != E; ++I) {
|
|
|
|
printVariableBody(I);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
// Finally, we can safely put out all of the function bodies.
|
|
|
|
nl(Out) << "// Function Definitions"; nl(Out);
|
|
|
|
for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (!I->isDeclaration()) {
|
|
|
|
nl(Out) << "// Function: " << I->getName() << " (" << getCppName(I)
|
|
|
|
<< ")";
|
|
|
|
nl(Out) << "{";
|
|
|
|
nl(Out,1);
|
|
|
|
printFunctionBody(I);
|
|
|
|
nl(Out,-1) << "}";
|
|
|
|
nl(Out);
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
void CppWriter::printProgram(const std::string& fname,
|
|
|
|
const std::string& mName) {
|
|
|
|
Out << "#include <llvm/Pass.h>\n";
|
2013-01-27 09:22:51 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "#include <llvm/ADT/SmallVector.h>\n";
|
|
|
|
Out << "#include <llvm/Analysis/Verifier.h>\n";
|
2013-01-27 09:22:51 +08:00
|
|
|
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";
|
2014-01-12 19:10:32 +08:00
|
|
|
Out << "#include <llvm/IR/IRPrintingPasses.h>\n";
|
2013-01-27 09:22:51 +08:00
|
|
|
Out << "#include <llvm/IR/InlineAsm.h>\n";
|
|
|
|
Out << "#include <llvm/IR/Instructions.h>\n";
|
|
|
|
Out << "#include <llvm/IR/LLVMContext.h>\n";
|
2015-02-13 18:01:29 +08:00
|
|
|
Out << "#include <llvm/IR/LegacyPassManager.h>\n";
|
2013-01-27 09:22:51 +08:00
|
|
|
Out << "#include <llvm/IR/Module.h>\n";
|
|
|
|
Out << "#include <llvm/Support/FormattedStream.h>\n";
|
|
|
|
Out << "#include <llvm/Support/MathExtras.h>\n";
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "#include <algorithm>\n";
|
|
|
|
Out << "using namespace llvm;\n\n";
|
|
|
|
Out << "Module* " << fname << "();\n\n";
|
|
|
|
Out << "int main(int argc, char**argv) {\n";
|
|
|
|
Out << " Module* Mod = " << fname << "();\n";
|
|
|
|
Out << " verifyModule(*Mod, PrintMessageAction);\n";
|
|
|
|
Out << " PassManager PM;\n";
|
|
|
|
Out << " PM.add(createPrintModulePass(&outs()));\n";
|
|
|
|
Out << " PM.run(*Mod);\n";
|
|
|
|
Out << " return 0;\n";
|
|
|
|
Out << "}\n\n";
|
|
|
|
printModule(fname,mName);
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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 << "\", getGlobalContext());";
|
|
|
|
if (!TheModule->getTargetTriple().empty()) {
|
2015-03-05 02:43:29 +08:00
|
|
|
nl(Out) << "mod->setDataLayout(\"" << TheModule->getDataLayoutStr()
|
|
|
|
<< "\");";
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
|
|
|
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";
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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;
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
Out << "\nFunction* " << fname << "(Module *mod) {\n";
|
|
|
|
printFunctionUses(F);
|
|
|
|
printFunctionHead(F);
|
|
|
|
printFunctionBody(F);
|
|
|
|
Out << "return " << getCppName(F) << ";\n";
|
|
|
|
Out << "}\n";
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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());
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
void CppWriter::printVariable(const std::string& fname,
|
|
|
|
const std::string& varName) {
|
|
|
|
const GlobalVariable* GV = TheModule->getNamedGlobal(varName);
|
2008-04-24 06:29:24 +08:00
|
|
|
|
2010-06-22 07:12:56 +08:00
|
|
|
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";
|
|
|
|
}
|
2008-04-24 06:29:24 +08:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
void CppWriter::printType(const std::string &fname,
|
|
|
|
const std::string &typeName) {
|
2011-07-18 12:54:35 +08:00
|
|
|
Type* Ty = TheModule->getTypeByName(typeName);
|
2010-06-22 07:12:56 +08:00
|
|
|
if (!Ty) {
|
|
|
|
error(std::string("Type '") + typeName + "' not found in input module");
|
|
|
|
return;
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
2010-06-22 07:12:56 +08:00
|
|
|
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;
|
2008-04-24 06:29:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
char CppWriter::ID = 0;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// External Interface declaration
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-04-15 06:14:34 +08:00
|
|
|
bool CPPTargetMachine::addPassesToEmitFile(
|
|
|
|
PassManagerBase &PM, raw_pwrite_stream &o, CodeGenFileType FileType,
|
2015-07-07 01:44:26 +08:00
|
|
|
bool DisableVerify, AnalysisID StartBefore, AnalysisID StartAfter,
|
|
|
|
AnalysisID StopAfter, MachineFunctionInitializer *MFInitializer) {
|
2015-04-10 05:06:08 +08:00
|
|
|
if (FileType != TargetMachine::CGFT_AssemblyFile)
|
|
|
|
return true;
|
|
|
|
auto FOut = llvm::make_unique<formatted_raw_ostream>(o);
|
|
|
|
PM.add(new CppWriter(std::move(FOut)));
|
2008-04-24 06:29:24 +08:00
|
|
|
return false;
|
|
|
|
}
|