diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-11-21 18:15:26 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-11-21 18:15:26 -0800 |
commit | b7e3f2ec069cb331749db389636f735551e37bdb (patch) | |
tree | 220767c0d61ba81c3d54a78456898e78c74f4d94 | |
parent | 902015756b37260b51e6da6a7c9ae67e96a55b52 (diff) |
merge in CppBackend work
-rw-r--r-- | lib/Target/CppBackend/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Target/CppBackend/CPPBackend.cpp | 1010 | ||||
-rw-r--r-- | lib/Target/CppBackend/Relooper.cpp | 1287 | ||||
-rw-r--r-- | lib/Target/CppBackend/Relooper.h | 251 | ||||
-rw-r--r-- | lib/Target/CppBackend/TargetInfo/CppBackendTargetInfo.cpp | 4 |
5 files changed, 2098 insertions, 455 deletions
diff --git a/lib/Target/CppBackend/CMakeLists.txt b/lib/Target/CppBackend/CMakeLists.txt index 515e1dd7e3..7e138b2695 100644 --- a/lib/Target/CppBackend/CMakeLists.txt +++ b/lib/Target/CppBackend/CMakeLists.txt @@ -1,5 +1,6 @@ add_llvm_target(CppBackendCodeGen CPPBackend.cpp + Relooper.cpp ) add_subdirectory(TargetInfo) diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 3e69098edc..299db973f8 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -38,6 +38,10 @@ #include <set> using namespace llvm; +#define dump(x, ...) fprintf(stderr, x, __VA_ARGS__) + +#include <Relooper.h> + static cl::opt<std::string> FuncName("cppfname", cl::desc("Specify the name of the generated function"), cl::value_desc("function name")); @@ -85,7 +89,10 @@ namespace { typedef std::set<std::string> NameSet; typedef std::set<Type*> TypeSet; typedef std::set<const Value*> ValueSet; + typedef std::map<std::string, Type::TypeID> VarMap; typedef std::map<const Value*,std::string> ForwardRefMap; + typedef std::vector<unsigned char> HeapData; + typedef std::pair<unsigned, unsigned> Address; /// CppWriter - This class is the main chunk of code that converts an LLVM /// module to a C++ translation unit. @@ -98,14 +105,20 @@ namespace { NameSet UsedNames; TypeSet DefinedTypes; ValueSet DefinedValues; + VarMap UsedVars; ForwardRefMap ForwardRefs; bool is_inline; unsigned indent_level; + HeapData GlobalData8; + HeapData GlobalData32; + HeapData GlobalData64; + std::map<std::string, Address> GlobalAddresses; public: static char ID; explicit CppWriter(formatted_raw_ostream &o) : - ModulePass(ID), Out(o), uniqueNum(0), is_inline(false), indent_level(0){} + ModulePass(ID), Out(o), uniqueNum(0), is_inline(false), indent_level(0){ + } virtual const char *getPassName() const { return "C++ backend"; } @@ -134,7 +147,28 @@ namespace { void printCallingConv(CallingConv::ID cc); void printEscapedString(const std::string& str); void printCFP(const ConstantFP* CFP); - + void printCommaSeparated(const HeapData v); + + void allocateConstant(const Constant* CV); + unsigned getGlobalAddress(const std::string &s) { + Address a = GlobalAddresses[s]; + switch (a.second) { + case 64: + return a.first + 8; + case 32: + return a.first + 8 + GlobalData64.size(); + case 8: + return a.first + 8 + GlobalData64.size() + GlobalData32.size(); + default: + assert(false); + } + } + std::string getPtrLoad(const Value* Ptr); + std::string getPtrUse(const Value* Ptr); + std::string getPtr(const Value* Ptr); + std::string getConstant(const Constant*); + std::string getValueAsStr(const Value*); + std::string getValueAsParenStr(const Value*); std::string getCppName(Type* val); inline void printCppName(Type* val); @@ -145,6 +179,10 @@ namespace { void printType(Type* Ty); void printTypes(const Module* M); + std::string getAssign(const StringRef &, const Type *); + std::string getCast(const StringRef &, const Type *); + std::string getParenCast(const StringRef &, const Type *); + void printConstant(const Constant *CPV); void printConstants(const Module* M); @@ -155,10 +193,14 @@ namespace { void printFunctionUses(const Function *F); void printFunctionHead(const Function *F); void printFunctionBody(const Function *F); - void printInstruction(const Instruction *I, const std::string& bbname); + std::string generateInstruction(const Instruction *I); std::string getOpName(const Value*); void printModuleBody(); + + unsigned stackAlign(unsigned x) { + return x + (x%4 != 0 ? 4 - x%4 : 0); + } }; } // end anonymous namespace. @@ -171,8 +213,8 @@ formatted_raw_ostream &CppWriter::nl(formatted_raw_ostream &Out, int delta) { } static inline void sanitize(std::string &str) { - for (size_t i = 0; i < str.length(); ++i) - if (!isalnum(str[i]) && str[i] != '_') + for (size_t i = 1; i < str.length(); ++i) + if (!isalnum(str[i]) && str[i] != '_' && str[i] != '$') str[i] = '_'; } @@ -217,8 +259,6 @@ void CppWriter::printCFP(const ConstantFP *CFP) { APFloat APF = APFloat(CFP->getValueAPF()); // copy if (CFP->getType() == Type::getFloatTy(CFP->getContext())) APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored); - Out << "ConstantFP::get(mod->getContext(), "; - Out << "APFloat("; #if HAVE_PRINTF_A char Buffer[100]; sprintf(Buffer, "%A", APF.convertToDouble()); @@ -257,11 +297,9 @@ void CppWriter::printCFP(const ConstantFP *CFP) { << utohexstr((uint32_t)CFP->getValueAPF(). bitcastToAPInt().getZExtValue()) << "U) /* " << StrVal << " */"; - Out << ")"; #if HAVE_PRINTF_A } #endif - Out << ")"; } void CppWriter::printCallingConv(CallingConv::ID cc){ @@ -423,40 +461,46 @@ 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; + return I->second; + + if (val->hasName()) { + if (dyn_cast<Function>(val)) { + name = std::string("_") + val->getName().str(); } else { - name = getTypePrefix(val->getType()); + name = std::string("$") + val->getName().str(); } + sanitize(name); } else { - name = getTypePrefix(val->getType()); - } - if (val->hasName()) - name += val->getName(); - else + if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(val)) { + name = std::string("gvar_") + + getTypePrefix(GV->getType()->getElementType()); + } else if (isa<Function>(val)) { + name = std::string("func_"); + } else if (const Constant* C = dyn_cast<Constant>(val)) { + name = std::string("const_") + getTypePrefix(C->getType()); + } else if (const Argument* Arg = dyn_cast<Argument>(val)) { + if (is_inline) { + unsigned argNum = std::distance(Arg->getParent()->arg_begin(), + Function::const_arg_iterator(Arg)) + 1; + name = std::string("arg_") + utostr(argNum); + NameSet::iterator NI = UsedNames.find(name); + if (NI != UsedNames.end()) + name += std::string("_") + utostr(uniqueNum++); + UsedNames.insert(name); + return ValueNames[val] = name; + } else { + name = getTypePrefix(val->getType()); + } + } else { + name = getTypePrefix(val->getType()); + } name += utostr(uniqueNum++); - sanitize(name); - NameSet::iterator NI = UsedNames.find(name); - if (NI != UsedNames.end()) - name += std::string("_") + utostr(uniqueNum++); - UsedNames.insert(name); + sanitize(name); + NameSet::iterator NI = UsedNames.find(name); + if (NI != UsedNames.end()) + name += std::string("_") + utostr(uniqueNum++); + UsedNames.insert(name); + } return ValueNames[val] = name; } @@ -710,6 +754,29 @@ void CppWriter::printTypes(const Module* M) { } +std::string CppWriter::getAssign(const StringRef &s, const Type *t) { + UsedVars[s] = t->getTypeID(); + return (s + " = ").str(); +} + +std::string CppWriter::getCast(const StringRef &s, const Type *t) { + switch (t->getTypeID()) { + default: + assert(false && "Unsupported type"); + case Type::FloatTyID: + // TODO return ("Math_fround(" + s + ")").str(); + case Type::DoubleTyID: + return ("+" + s).str(); + case Type::IntegerTyID: + case Type::PointerTyID: + return (s + "|0").str(); + } +} + +std::string CppWriter::getParenCast(const StringRef &s, const Type *t) { + return getCast(("(" + s + ")").str(), t); +} + // printConstant - Print out a constant pool entry... void CppWriter::printConstant(const Constant *CV) { // First, if the constant is actually a GlobalValue (variable or function) @@ -721,20 +788,16 @@ void CppWriter::printConstant(const Constant *CV) { std::string constName(getCppName(CV)); std::string typeName(getCppName(CV->getType())); + //Out << "var " << constName << " = "; + 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));"; + Out << constValue << ";"; } else if (isa<ConstantAggregateZero>(CV)) { - Out << "ConstantAggregateZero* " << constName - << " = ConstantAggregateZero::get(" << typeName << ");"; + Out << "ConstantAggregateZero::get(" << typeName << ");"; } else if (isa<ConstantPointerNull>(CV)) { - Out << "ConstantPointerNull* " << constName - << " = ConstantPointerNull::get(" << typeName << ");"; + Out << "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)) { @@ -779,20 +842,13 @@ void CppWriter::printConstant(const Constant *CV) { } else if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(CV)) { if (CDS->isString()) { - Out << "Constant *" << constName << - " = ConstantDataArray::getString(mod->getContext(), \""; + Out << "allocate(["; StringRef Str = CDS->getAsString(); - bool nullTerminate = false; - if (Str.back() == 0) { - Str = Str.drop_back(); - nullTerminate = true; + for (unsigned int i = 0; i < Str.size(); i++) { + Out << (unsigned int)(Str.data()[i]); + if (i < Str.size()-1) Out << ","; } - printEscapedString(Str); - // Determine if we want null termination or not. - if (nullTerminate) - Out << "\", true);"; - else - Out << "\", false);";// No null terminator + Out << "], 'i8', ALLOC_STATIC);"; } else { // TODO: Could generate more efficient code generating CDS calls instead. Out << "std::vector<Constant*> " << constName << "_elems;"; @@ -813,19 +869,12 @@ void CppWriter::printConstant(const Constant *CV) { } } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { if (CE->getOpcode() == Instruction::GetElementPtr) { - Out << "std::vector<Constant*> " << constName << "_indices;"; - nl(Out); - printConstant(CE->getOperand(0)); - for (unsigned i = 1; i < CE->getNumOperands(); ++i ) { - printConstant(CE->getOperand(i)); - Out << constName << "_indices.push_back(" - << getCppName(CE->getOperand(i)) << ");"; - nl(Out); + Out << "allocate(["; + for (unsigned i = 0; i < CE->getNumOperands(); ++i ) { + Out << getCppName(CE->getOperand(i)); + if (i < CE->getNumOperands()-1) Out << ","; } - Out << "Constant* " << constName - << " = ConstantExpr::getGetElementPtr(" - << getCppName(CE->getOperand(0)) << ", " - << constName << "_indices);"; + Out << "], 'i32', ALLOC_STATIC);"; } else if (CE->isCast()) { printConstant(CE->getOperand(0)); Out << "Constant* " << constName << " = ConstantExpr::getCast("; @@ -936,8 +985,11 @@ 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()); + if (I->hasInitializer()) { + const Constant *CV = I->getInitializer(); + allocateConstant(CV); + GlobalAddresses[I->getName().str()] = GlobalAddresses[getCppName(CV)]; + } // Traverse the LLVM functions looking for constants for (Module::const_iterator FI = TheModule->begin(), FE = TheModule->end(); @@ -949,7 +1001,7 @@ void CppWriter::printConstants(const Module* M) { ++I) { for (unsigned i = 0; i < I->getNumOperands(); ++i) { if (Constant* C = dyn_cast<Constant>(I->getOperand(i))) { - printConstant(C); + allocateConstant(C); } } } @@ -958,91 +1010,19 @@ void CppWriter::printConstants(const Module* M) { } void CppWriter::printVariableUses(const GlobalVariable *GV) { - nl(Out) << "// Type Definitions"; - nl(Out); - printType(GV->getType()); - if (GV->hasInitializer()) { - const Constant *Init = GV->getInitializer(); - printType(Init->getType()); - if (const Function *F = dyn_cast<Function>(Init)) { - nl(Out)<< "/ Function Declarations"; nl(Out); - printFunctionHead(F); - } else if (const GlobalVariable* gv = dyn_cast<GlobalVariable>(Init)) { - nl(Out) << "// Global Variable Declarations"; nl(Out); - printVariableHead(gv); - - nl(Out) << "// Global Variable Definitions"; nl(Out); - printVariableBody(gv); - } else { - nl(Out) << "// Constant Definitions"; nl(Out); - printConstant(Init); - } - } } void CppWriter::printVariableHead(const GlobalVariable *GV) { - nl(Out) << "GlobalVariable* " << getCppName(GV); - if (is_inline) { - Out << " = mod->getGlobalVariable(mod->getContext(), "; - printEscapedString(GV->getName()); - Out << ", " << getCppName(GV->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()); - Out << "\");"; - nl(Out); - } - if (GV->getAlignment()) { - printCppName(GV); - Out << "->setAlignment(" << utostr(GV->getAlignment()) << ");"; - nl(Out); - } - if (GV->getVisibility() != GlobalValue::DefaultVisibility) { - printCppName(GV); - Out << "->setVisibility("; - printVisibilityType(GV->getVisibility()); - Out << ");"; - nl(Out); - } - if (GV->isThreadLocal()) { - printCppName(GV); - Out << "->setThreadLocalMode("; - printThreadLocalMode(GV->getThreadLocalMode()); - Out << ");"; - nl(Out); - } - if (is_inline) { - out(); Out << "}"; nl(Out); - } + Out << "var "; + printCppName(GV); + Out << ";\n"; } void CppWriter::printVariableBody(const GlobalVariable *GV) { if (GV->hasInitializer()) { printCppName(GV); - Out << "->setInitializer("; - Out << getCppName(GV->getInitializer()) << ");"; + Out << " = "; + Out << getCppName(GV->getInitializer()) << ";"; nl(Out); } } @@ -1091,9 +1071,98 @@ static StringRef ConvertAtomicSynchScope(SynchronizationScope SynchScope) { llvm_unreachable("Unknown synch scope"); } -// printInstruction - This member is called for each Instruction in a function. -void CppWriter::printInstruction(const Instruction *I, - const std::string& bbname) { +std::string CppWriter::getPtrLoad(const Value* Ptr) { + Type *t = cast<PointerType>(Ptr->getType())->getElementType(); + return getCast(getPtrUse(Ptr), t); +} + +std::string CppWriter::getPtrUse(const Value* Ptr) { + Type *t = cast<PointerType>(Ptr->getType())->getElementType(); + if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr)) { + std::string text = ""; + unsigned Addr = getGlobalAddress(GV->getName().str()); + switch (t->getTypeID()) { + default: + assert(false && "Unsupported type"); + case Type::DoubleTyID: + return "HEAPF64[" + utostr(Addr >> 3) + "]"; + case Type::FloatTyID: + return "HEAPF32[" + utostr(Addr >> 2) + "]"; + case Type::IntegerTyID: + return "HEAP32[" + utostr(Addr >> 2) + "]"; + } + } else { + switch (t->getTypeID()) { + default: + assert(false && "Unsupported type"); + case Type::DoubleTyID: + return "HEAPF64[" + getOpName(Ptr) + ">>3]"; + case Type::FloatTyID: + return "HEAPF32[" + getOpName(Ptr) + ">>2]"; + case Type::IntegerTyID: + case Type::PointerTyID: + return "HEAP32[" + getOpName(Ptr) + ">>2]"; + } + } +} + +std::string CppWriter::getPtr(const Value* Ptr) { + Type *t = cast<PointerType>(Ptr->getType())->getElementType(); + if (const Constant *CV = dyn_cast<Constant>(Ptr)) { + std::string text = ""; + unsigned Addr = getGlobalAddress(CV->getName().str()); + switch (t->getTypeID()) { + default: + assert(false && "Unsupported type"); + case Type::DoubleTyID: + return utostr(Addr >> 3); + case Type::FloatTyID: + return utostr(Addr >> 2); + case Type::ArrayTyID: + case Type::StructTyID: + case Type::PointerTyID: + case Type::VectorTyID: + case Type::IntegerTyID: + return utostr(Addr >> 2); + } + } else { + return getOpName(Ptr) + "|0"; + } +} + +std::string CppWriter::getConstant(const Constant* CV) { + if (/* const PointerType *Ptr = */ dyn_cast<PointerType>(CV->getType())) { + return getPtr(CV); + } else { + if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) { + std::string S = ftostr(CFP->getValueAPF()); + S = '+' + S; +// if (S.find('.') == S.npos) { TODO: do this when necessary, but it is necessary even for 0.0001 + return S; + } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { + return CI->getValue().toString(10, true); + } else { + assert(false); + } + } +} + +std::string CppWriter::getValueAsStr(const Value* V) { + if (const Constant *CV = dyn_cast<Constant>(V)) { + return getConstant(CV); + } else { + return getCast(getCppName(V), V->getType()); + } +} + +std::string CppWriter::getValueAsParenStr(const Value* V) { + return "(" + getValueAsStr(V) + ")"; +} + +// generateInstruction - This member is called for each Instruction in a function. +std::string CppWriter::generateInstruction(const Instruction *I) { + std::string text = "NYI: " + std::string(I->getOpcodeName()); + std::string bbname = "NO_BBNAME"; std::string iName(getCppName(I)); // Before we emit this instruction, we need to take care of generating any @@ -1110,24 +1179,18 @@ void CppWriter::printInstruction(const Instruction *I, case Instruction::Ret: { const ReturnInst* ret = cast<ReturnInst>(I); - Out << "ReturnInst::Create(mod->getContext(), " - << (ret->getReturnValue() ? opNames[0] + ", " : "") << bbname << ");"; + Value *RV = ret->getReturnValue(); + text = "STACKTOP = sp;"; + text += "return"; + if (RV == NULL) { + text += ";"; + } else { + text += " " + getValueAsStr(RV) + ";"; + } break; } case Instruction::Br: { - const BranchInst* br = cast<BranchInst>(I); - Out << "BranchInst::Create(" ; - if (br->getNumOperands() == 3) { - Out << opNames[2] << ", " - << opNames[1] << ", " - << opNames[0] << ", "; - - } else if (br->getNumOperands() == 1) { - Out << opNames[0] << ", "; - } else { - error("Branch with 2 operands?"); - } - Out << bbname << ");"; + text = ""; break; } case Instruction::Switch: { @@ -1213,14 +1276,15 @@ void CppWriter::printInstruction(const Instruction *I, case Instruction::Shl: case Instruction::LShr: case Instruction::AShr:{ - Out << "BinaryOperator* " << iName << " = BinaryOperator::Create("; + //Out << "BinaryOperator* " << iName << " = BinaryOperator::Create("; + text = getAssign(iName, Type::getInt32Ty(I->getContext())); switch (I->getOpcode()) { - case Instruction::Add: Out << "Instruction::Add"; break; + case Instruction::Add: text += getParenCast(getValueAsParenStr(I->getOperand(0)) + " + " + getValueAsParenStr(I->getOperand(1)), Type::getInt32Ty(I->getContext())) + ";"; break; case Instruction::FAdd: Out << "Instruction::FAdd"; break; - case Instruction::Sub: Out << "Instruction::Sub"; break; + case Instruction::Sub: text += getParenCast(getValueAsParenStr(I->getOperand(0)) + " - " + getValueAsParenStr(I->getOperand(1)), Type::getInt32Ty(I->getContext())) + ";"; break; case Instruction::FSub: Out << "Instruction::FSub"; break; case Instruction::Mul: Out << "Instruction::Mul"; break; - case Instruction::FMul: Out << "Instruction::FMul"; break; + case Instruction::FMul: text += getParenCast(getValueAsStr(I->getOperand(0)) + " * " + getValueAsStr(I->getOperand(1)), I->getType()) + ";"; break; case Instruction::UDiv:Out << "Instruction::UDiv"; break; case Instruction::SDiv:Out << "Instruction::SDiv"; break; case Instruction::FDiv:Out << "Instruction::FDiv"; break; @@ -1235,9 +1299,9 @@ void CppWriter::printInstruction(const Instruction *I, case Instruction::AShr:Out << "Instruction::AShr"; break; default: Out << "Instruction::BadOpCode"; break; } - Out << ", " << opNames[0] << ", " << opNames[1] << ", \""; - printEscapedString(I->getName()); - Out << "\", " << bbname << ");"; + //Out << ", " << opNames[0] << ", " << opNames[1] << ", \""; + //printEscapedString(I->getName()); + //Out << "\", " << bbname << ");"; break; } case Instruction::FCmp: { @@ -1267,96 +1331,59 @@ void CppWriter::printInstruction(const Instruction *I, break; } case Instruction::ICmp: { - Out << "ICmpInst* " << iName << " = new ICmpInst(*" << bbname << ", "; + text = getAssign(iName, Type::getInt32Ty(I->getContext())) + "(" + getValueAsStr(I->getOperand(0)) + ")"; 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; + case ICmpInst::ICMP_EQ: text += "=="; break; + case ICmpInst::ICMP_NE: text += "!="; break; + // TODO: handle signed and unsigned + case ICmpInst::ICMP_ULE: text += "<="; break; + case ICmpInst::ICMP_SLE: text += "<="; break; + case ICmpInst::ICMP_UGE: text += ">="; break; + case ICmpInst::ICMP_SGE: text += ">="; break; + case ICmpInst::ICMP_ULT: text += "<"; break; + case ICmpInst::ICMP_SLT: text += "<"; break; + case ICmpInst::ICMP_UGT: text += ">"; break; + case ICmpInst::ICMP_SGT: text += ">"; break; + default: text += "ICmpInst::BAD_ICMP_PREDICATE"; break; } - Out << ", " << opNames[0] << ", " << opNames[1] << ", \""; - printEscapedString(I->getName()); - Out << "\");"; + text += "(" + getValueAsStr(I->getOperand(1)) + ")"; 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() << ");"; + Type *t = allocaI->getAllocatedType(); + unsigned size; + if (ArrayType *AT = dyn_cast<ArrayType>(t)) { + size = AT->getElementType()->getScalarSizeInBits()/8 * AT->getNumElements(); + } else { + size = t->getScalarSizeInBits()/8; + } + text = getAssign(iName, Type::getInt32Ty(I->getContext())) + "STACKTOP; STACKTOP = STACKTOP + " + Twine(stackAlign(size)).str() + "|0;"; break; } case Instruction::Load: { - const LoadInst* load = cast<LoadInst>(I); - Out << "LoadInst* " << iName << " = new LoadInst(" - << opNames[0] << ", \""; - printEscapedString(load->getName()); - Out << "\", " << (load->isVolatile() ? "true" : "false" ) - << ", " << bbname << ");"; - 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 << ");"; - } + const LoadInst *LI = cast<LoadInst>(I); + const Value *Ptr = LI->getPointerOperand(); + Type *t = cast<PointerType>(Ptr->getType())->getElementType(); + text = getAssign(iName, t) + getPtrLoad(Ptr) + ";"; break; } case Instruction::Store: { - const StoreInst* store = cast<StoreInst>(I); - Out << "StoreInst* " << iName << " = new StoreInst(" - << opNames[0] << ", " - << opNames[1] << ", " - << (store->isVolatile() ? "true" : "false") - << ", " << bbname << ");"; - if (store->getAlignment()) - nl(Out) << iName << "->setAlignment(" - << store->getAlignment() << ");"; - if (store->isAtomic()) { - StringRef Ordering = ConvertAtomicOrdering(store->getOrdering()); - StringRef CrossThread = ConvertAtomicSynchScope(store->getSynchScope()); - nl(Out) << iName << "->setAtomic(" - << Ordering << ", " << CrossThread << ");"; + const StoreInst *SI = cast<StoreInst>(I); + const Value *P = SI->getPointerOperand(); + const Value *V = SI->getValueOperand(); + std::string VS = getValueAsStr(V); + if (V->getType()->isDoubleTy() && SI->getAlignment() == 4) { + // only 4-byte aligned, copy carefully + std::string PS = getOpName(P); + text = "HEAPF64[tempDoublePtr>>3]=" + VS + ";HEAPF32[" + PS + ">>2]=HEAPF32[tempDoublePtr>>2];HEAPF32[" + PS + "+4>>2]=HEAPF32[tempDoublePtr+4>>2];"; + } else { + text = getPtrUse(P) + " = " + VS + ";"; } 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;"; - nl(Out); - for (unsigned i = 1; i < gep->getNumOperands(); ++i ) { - Out << iName << "_indices.push_back(" - << opNames[i] << ");"; - nl(Out); - } - Out << "Instruction* " << iName << " = GetElementPtrInst::Create(" - << opNames[0] << ", " << iName << "_indices"; - } - Out << ", \""; - printEscapedString(gep->getName()); - Out << "\", " << bbname << ");"; + assert(false && "Unhandled instruction"); break; } case Instruction::PHI: { @@ -1376,6 +1403,18 @@ void CppWriter::printInstruction(const Instruction *I, } break; } + case Instruction::PtrToInt: + text = getAssign(iName, Type::getInt32Ty(I->getContext())); + if (const Constant *CV = dyn_cast<Constant>(I->getOperand(0))) { + text += utostr(getGlobalAddress(CV->getName().str())); + } else { + text += getCast(opNames[0], Type::getInt32Ty(I->getContext())); + } + text += ";"; + break; + case Instruction::IntToPtr: + text = getAssign(iName, Type::getInt32Ty(I->getContext())) + opNames[0] + ";"; + break; case Instruction::Trunc: case Instruction::ZExt: case Instruction::SExt: @@ -1385,71 +1424,45 @@ void CppWriter::printInstruction(const Instruction *I, 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::FPExt: text = getAssign(iName, Type::getFloatTy(I->getContext())) + opNames[0] + ";"; 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; + case Instruction::SIToFP: + case Instruction::BitCast: text = getAssign(iName, I->getOperand(0)->getType()) + getValueAsStr(I->getOperand(0)) + ";"; break; default: llvm_unreachable("Unreachable"); } - Out << "(" << opNames[0] << ", " - << getCppName(cst->getType()) << ", \""; - printEscapedString(cst->getName()); - Out << "\", " << bbname << ");"; break; } case Instruction::Call: { const CallInst* call = cast<CallInst>(I); - if (const InlineAsm* ila = dyn_cast<InlineAsm>(call->getCalledValue())) { - Out << "InlineAsm* " << getCppName(ila) << " = InlineAsm::get(" - << getCppName(ila->getFunctionType()) << ", \"" - << ila->getAsmString() << "\", \"" - << ila->getConstraintString() << "\"," - << (ila->hasSideEffects() ? "true" : "false") << ");"; - nl(Out); - } - if (call->getNumArgOperands() > 1) { - Out << "std::vector<Value*> " << iName << "_params;"; - nl(Out); - for (unsigned i = 0; i < call->getNumArgOperands(); ++i) { - Out << iName << "_params.push_back(" << opNames[i] << ");"; - nl(Out); + const int numArgs = call->getNumArgOperands(); + Type *RT = call->getCalledFunction()->getReturnType(); + text = opNames[numArgs] + "("; + for (int i = 0; i < numArgs; i++) { + Value *Arg = call->getArgOperand(i); + Type *t = dyn_cast<PointerType>(Arg->getType()); + const GlobalVariable *GV; + if (t && (GV = dyn_cast<GlobalVariable>(Arg))) { + text += utostr(getGlobalAddress(GV->getName().str())); + } else { + text += getValueAsStr(call->getArgOperand(i)); } - Out << "CallInst* " << iName << " = CallInst::Create(" - << opNames[call->getNumArgOperands()] << ", " - << iName << "_params, \""; - } else if (call->getNumArgOperands() == 1) { - Out << "CallInst* " << iName << " = CallInst::Create(" - << opNames[call->getNumArgOperands()] << ", " << opNames[0] << ", \""; - } else { - Out << "CallInst* " << iName << " = CallInst::Create(" - << opNames[call->getNumArgOperands()] << ", \""; + if (i < numArgs - 1) text += ", "; } - printEscapedString(call->getName()); - Out << "\", " << bbname << ");"; - nl(Out) << iName << "->setCallingConv("; - printCallingConv(call->getCallingConv()); - Out << ");"; - nl(Out) << iName << "->setTailCall(" - << (call->isTailCall() ? "true" : "false"); - Out << ");"; - nl(Out); - printAttributes(call->getAttributes(), iName); - Out << iName << "->setAttributes(" << iName << "_PAL);"; - nl(Out); + text += ")"; + if (!RT->isVoidTy()) { + text = getAssign(iName, RT) + getCast(text, RT); + } + text += ";"; break; } case Instruction::Select: { @@ -1591,8 +1604,8 @@ void CppWriter::printInstruction(const Instruction *I, } } DefinedValues.insert(I); - nl(Out); delete [] opNames; + return text; } // Print out the types, constants and declarations needed by one function @@ -1654,42 +1667,6 @@ void CppWriter::printFunctionUses(const Function* F) { } } - // Print the function declarations for any functions encountered - nl(Out) << "// Function Declarations"; nl(Out); - for (SmallPtrSet<GlobalValue*,64>::iterator I = gvs.begin(), E = gvs.end(); - I != E; ++I) { - if (Function* Fun = dyn_cast<Function>(*I)) { - if (!is_inline || Fun != F) - printFunctionHead(Fun); - } - } - - // Print the global variable declarations for any variables encountered - nl(Out) << "// Global Variable Declarations"; nl(Out); - for (SmallPtrSet<GlobalValue*,64>::iterator I = gvs.begin(), E = gvs.end(); - I != E; ++I) { - if (GlobalVariable* F = dyn_cast<GlobalVariable>(*I)) - printVariableHead(F) |