From 9ddc86c6e51617d1170eed07a4320edf6679f655 Mon Sep 17 00:00:00 2001 From: Sumant Kowshik Date: Wed, 8 May 2002 18:09:58 +0000 Subject: *** empty log message *** git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2552 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Assembly/CWriter.h | 21 + lib/Makefile | 2 +- lib/Target/CBackend/CBackend.cpp | 1415 ++++++++++++++++++++++++++++++++++++++ lib/Target/CBackend/Makefile | 7 + lib/Target/CBackend/Writer.cpp | 1415 ++++++++++++++++++++++++++++++++++++++ tools/dis/Makefile | 2 +- tools/dis/dis.cpp | 20 +- tools/llvm-dis/Makefile | 2 +- tools/llvm-dis/dis.cpp | 20 +- tools/llvm-dis/llvm-dis.cpp | 20 +- 10 files changed, 2909 insertions(+), 15 deletions(-) create mode 100644 include/llvm/Assembly/CWriter.h create mode 100644 lib/Target/CBackend/CBackend.cpp create mode 100644 lib/Target/CBackend/Makefile create mode 100644 lib/Target/CBackend/Writer.cpp diff --git a/include/llvm/Assembly/CWriter.h b/include/llvm/Assembly/CWriter.h new file mode 100644 index 0000000000..b42e16c196 --- /dev/null +++ b/include/llvm/Assembly/CWriter.h @@ -0,0 +1,21 @@ +//===-- llvm/CGen/Writer.h - Printer for VM assembly files -------*- C++ -*--=// +// +// This functionality is implemented by the lib/CWriter library. +// This library is used to print C language files to an iostream. +// +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_C_WRITER_H +#define LLVM_C_WRITER_H + +class Module; + +#include + +void WriteToC(const Module *Module, std::ostream &o); + +#endif + + + diff --git a/lib/Makefile b/lib/Makefile index 8d8ce170d4..eea7ca090d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,5 +1,5 @@ LEVEL = .. -DIRS = VMCore Analysis Transforms AsmParser Bytecode Support CodeGen Target +DIRS = VMCore Analysis Transforms AsmParser Bytecode Support CodeGen Target CWriter include $(LEVEL)/Makefile.common diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp new file mode 100644 index 0000000000..02d470cf3f --- /dev/null +++ b/lib/Target/CBackend/CBackend.cpp @@ -0,0 +1,1415 @@ +//===-- Writer.cpp - Library for writing C files -----------------*- C++ -*--=// +// +// This library implements the functionality defined in llvm/Assembly/CWriter.h +// and CLocalVars.h +// +// TODO : Recursive types. +//===-----------------------------------------------------------------------==// +#include "llvm/Assembly/CWriter.h" +#include "CLocalVars.h" +#include "llvm/SlotCalculator.h" +#include "llvm/Module.h" +#include "llvm/Argument.h" +#include "llvm/Function.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Constants.h" +#include "llvm/GlobalVariable.h" +#include "llvm/BasicBlock.h" +#include "llvm/iMemory.h" +#include "llvm/iTerminators.h" +#include "llvm/iPHINode.h" +#include "llvm/iOther.h" +#include "llvm/SymbolTable.h" +#include "llvm/Support/InstVisitor.h" +#include "Support/StringExtras.h" +#include "Support/STLExtras.h" + +#include +#include +using std::string; +using std::map; +using std::vector; +using std::ostream; + +/* Implementation of the CLocalVars methods */ + +// Appends a variable to the LocalVars map if it does not already exist +// Also check that the type exists on the map. +void CLocalVars::addLocalVar(const Type *t, const string & var) { + if (!LocalVars.count(t) || + find(LocalVars[t].begin(), LocalVars[t].end(), var) + == LocalVars[t].end()) { + LocalVars[t].push_back(var); + } +} + +/* Writer.cpp */ +static string calcTypeNameVar(const Type *Ty, vector &TypeStack, + map &TypeNames, + string VariableName, string NameSoFar); + +static std::string getConstStrValue(const Constant* CPV); + + +// +//Getting opcodes in terms of the operator +// +static const char *getOpcodeOperName(const Instruction *I) { + switch (I->getOpcode()) { + // Standard binary operators... + case Instruction::Add: return "+"; + case Instruction::Sub: return "-"; + case Instruction::Mul: return "*"; + case Instruction::Div: return "/"; + case Instruction::Rem: return "%"; + + // Logical operators... + case Instruction::And: return "&"; + case Instruction::Or: return "|"; + case Instruction::Xor: return "^"; + + // SetCond operators... + case Instruction::SetEQ: return "=="; + case Instruction::SetNE: return "!="; + case Instruction::SetLE: return "<="; + case Instruction::SetGE: return ">="; + case Instruction::SetLT: return "<"; + case Instruction::SetGT: return ">"; + + //ShiftInstruction... + + case Instruction::Shl : return "<<"; + case Instruction::Shr : return ">>"; + + default: + cerr << "Invalid operator type!" << I->getOpcode() << "\n"; + abort(); + } + return 0; +} + + +// We dont want identifier names with ., space, - in them. +// So we replace them with _ +static string makeNameProper(string x) { + string tmp; + for (string::iterator sI = x.begin(), sEnd = x.end(); sI != sEnd; sI++) { + if (*sI == '.') + tmp += '_'; + else if (*sI == ' ') + tmp += '_'; + else if (*sI == '-') + tmp += "__"; + else + tmp += *sI; + } + return tmp; +} + +static string getConstantName(const Constant *CPV) { + return CPV->getName(); +} + + +static std::string getConstArrayStrValue(const Constant* CPV) { + std::string Result; + + // As a special case, print the array as a string if it is an array of + // ubytes or an array of sbytes with positive values. + // + const Type *ETy = cast(CPV->getType())->getElementType(); + bool isString = (ETy == Type::SByteTy || ETy == Type::UByteTy); + + if (ETy == Type::SByteTy) { + for (unsigned i = 0; i < CPV->getNumOperands(); ++i) + if (ETy == Type::SByteTy && + cast(CPV->getOperand(i))->getValue() < 0) { + isString = false; + break; + } + } + + if (isString) { + Result = "\""; + for (unsigned i = 0; i < CPV->getNumOperands(); ++i) { + unsigned char C = (ETy == Type::SByteTy) ? + (unsigned char)cast(CPV->getOperand(i))->getValue() : + (unsigned char)cast(CPV->getOperand(i))->getValue(); + + if (isprint(C)) { + Result += C; + } else { + Result += '\\'; + Result += 'x'; + Result += ( C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A'); + Result += ((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'); + } + } + Result += "\""; + + } else { + Result = "{"; + if (CPV->getNumOperands()) { + Result += " " + getConstStrValue(cast(CPV->getOperand(0))); + for (unsigned i = 1; i < CPV->getNumOperands(); i++) + Result += ", " + getConstStrValue(cast(CPV->getOperand(i))); + } + Result += " }"; + } + + return Result; +} + +static std::string getConstStructStrValue(const Constant* CPV) { + std::string Result = "{"; + if (CPV->getNumOperands()) { + Result += " " + getConstStrValue(cast(CPV->getOperand(0))); + for (unsigned i = 1; i < CPV->getNumOperands(); i++) + Result += ", " + getConstStrValue(cast(CPV->getOperand(i))); + } + + return Result + " }"; +} + +// our own getStrValue function for constant initializers +static std::string getConstStrValue(const Constant* CPV) { + // Does not handle null pointers, that needs to be checked explicitly + string tempstr; + if (CPV == ConstantBool::False) + return "0"; + else if (CPV == ConstantBool::True) + return "1"; + + else if (isa(CPV)) { + tempstr = getConstArrayStrValue(CPV); + } + else if (isa(CPV)) { + tempstr = getConstStructStrValue(CPV); + } + else if (ConstantUInt *CUI = dyn_cast(CPV)) { + tempstr = utostr((long long unsigned int) CUI->getValue()); + } + else if (ConstantSInt *CSI = dyn_cast(CPV)) { + tempstr = itostr(CSI->getValue()); + } + else if (ConstantFP *CFP = dyn_cast(CPV)) { + tempstr = ftostr(CFP->getValue()); + } + + if (CPV->getType() == Type::ULongTy) + tempstr += "ull"; + else if (CPV->getType() == Type::LongTy) + tempstr += "ll"; + else if (CPV->getType() == Type::UIntTy || + CPV->getType() == Type::UShortTy) + tempstr += "u"; + + return tempstr; + +} + +// WriteCOperand - Write the name of the specified value out to the specified +// ostream. This can be useful when you just want to print int %0 not the +// whole instruction that generated it. +// +static void WriteCOperandInternal(ostream &Out, const Value *V, + bool PrintName, SlotCalculator *Table, + string &OperandType) { + int Slot; + if (PrintName && V->hasName()) { + // If V has a name. + Out << "llvm__" << makeNameProper(V->getName()) << "_" << + (V->getType())->getUniqueID(); + return; + } + else if (const Constant *CPV = dyn_cast(V)) { + if (isa(CPV)) { + Out << "(" << OperandType << ")0"; + } + else + Out << getConstStrValue(CPV); + } + else { + Slot = Table->getValSlot(V); + if (Slot >= 0) + Out << "llvm__tmp_" << Slot << "_" << V->getType()->getUniqueID(); + else if (PrintName) + Out << ""; + } +} + +// Internal function +// Essentially pass the Type* variable, an empty typestack and this prints +// out the C type +static string calcTypeName(const Type *Ty, vector &TypeStack, + map &TypeNames, + string *FunctionInfo) { + + // Takin' care of the fact that boolean would be int in C + // and that ushort would be unsigned short etc. + + // Base Case + if (Ty->isPrimitiveType()) + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + return "int"; + break; + case Type::UByteTyID: + return "unsigned char"; + break; + case Type::SByteTyID: + return "signed char"; + break; + case Type::UShortTyID: + return "unsigned long long"; + break; + case Type::ULongTyID: + return "unsigned long long"; + break; + case Type::LongTyID: + return "signed long long"; + break; + case Type::UIntTyID: + return "unsigned int"; + break; + default : + return Ty->getDescription(); + } + + // Check to see if the type is named. + map::iterator I = TypeNames.find(Ty); + if (I != TypeNames.end()) + return I->second; + + // Check to see if the Type is already on the stack... + unsigned Slot = 0, CurSize = TypeStack.size(); + while (Slot < CurSize && TypeStack[Slot] != Ty) ++Slot; // Scan for type + + // This is another base case for the recursion. In this case, we know + // that we have looped back to a type that we have previously visited. + // Generate the appropriate upreference to handle this. + // + if (Slot < CurSize) + return "\\" + utostr(CurSize-Slot); // Here's the upreference + + TypeStack.push_back(Ty); // Recursive case: Add us to the stack.. + + string Result; + string MInfo = ""; + switch (Ty->getPrimitiveID()) { + case Type::FunctionTyID: { + const FunctionType *MTy = cast(Ty); + Result = calcTypeName(MTy->getReturnType(), TypeStack, TypeNames, &MInfo); + if (MInfo != "") + Result += ") " + MInfo; + Result += "("; + *FunctionInfo += " ("; + for (FunctionType::ParamTypes::const_iterator + I = MTy->getParamTypes().begin(), + E = MTy->getParamTypes().end(); I != E; ++I) { + if (I != MTy->getParamTypes().begin()) + *FunctionInfo += ", "; + MInfo = ""; + *FunctionInfo += calcTypeName(*I, TypeStack, TypeNames, &MInfo); + if (MInfo != "") + Result += ") " + MInfo; + } + if (MTy->isVarArg()) { + if (!MTy->getParamTypes().empty()) + *FunctionInfo += ", "; + *FunctionInfo += "..."; + } + *FunctionInfo += ")"; + break; + } + case Type::StructTyID: { + string tempstr = ""; + const StructType *STy = cast(Ty); + Result = " struct {\n "; + int indx = 0; + for (StructType::ElementTypes::const_iterator + I = STy->getElementTypes().begin(), + E = STy->getElementTypes().end(); I != E; ++I) { + Result += calcTypeNameVar(*I, TypeStack, TypeNames, + "field" + itostr(indx++), tempstr); + Result += ";\n "; + } + Result += " } "; + break; + } + case Type::PointerTyID: + Result = calcTypeName(cast(Ty)->getElementType(), + TypeStack, TypeNames, &MInfo); + Result += "*"; + break; + case Type::ArrayTyID: { + const ArrayType *ATy = cast(Ty); + int NumElements = ATy->getNumElements(); + Result = calcTypeName(ATy->getElementType(), TypeStack, TypeNames, &MInfo); + Result += "*"; + break; + } + default: + assert(0 && "Unhandled case in getTypeProps!"); + Result = ""; + } + + TypeStack.pop_back(); // Remove self from stack... + return Result; +} + +// Internal function +// Pass the Type* variable and and the variable name and this prints out the +// variable declaration. +// This is different from calcTypeName because if you need to declare an array +// the size of the array would appear after the variable name itself +// For eg. int a[10]; +static string calcTypeNameVar(const Type *Ty, vector &TypeStack, + map &TypeNames, + string VariableName, string NameSoFar) { + if (Ty->isPrimitiveType()) + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + return "int " + NameSoFar + VariableName; + break; + case Type::UByteTyID: + return "unsigned char " + NameSoFar + VariableName; + break; + case Type::SByteTyID: + return "signed char " + NameSoFar + VariableName; + break; + case Type::UShortTyID: + return "unsigned long long " + NameSoFar + VariableName; + break; + case Type::ULongTyID: + return "unsigned long long " + NameSoFar + VariableName; + break; + case Type::LongTyID: + return "signed long long " + NameSoFar + VariableName; + break; + case Type::UIntTyID: + return "unsigned int " + NameSoFar + VariableName; + break; + default : + return Ty->getDescription() + " " + NameSoFar + VariableName; + } + + // Check to see if the type is named. + map::iterator I = TypeNames.find(Ty); + if (I != TypeNames.end()) + return I->second + " " + NameSoFar + VariableName; + + // Check to see if the Type is already on the stack... + unsigned Slot = 0, CurSize = TypeStack.size(); + while (Slot < CurSize && TypeStack[Slot] != Ty) ++Slot; // Scan for type + + if (Slot < CurSize) + return "\\" + utostr(CurSize-Slot) + " " + NameSoFar + VariableName; + // Here's the upreference + + TypeStack.push_back(Ty); // Recursive case: Add us to the stack.. + + string Result; + string tempstr = ""; + + switch (Ty->getPrimitiveID()) { + case Type::FunctionTyID: { + string MInfo = ""; + const FunctionType *MTy = cast(Ty); + Result += calcTypeName(MTy->getReturnType(), TypeStack, TypeNames, &MInfo); + if (MInfo != "") + Result += ") " + MInfo; + Result += " " + NameSoFar + VariableName; + Result += " ("; + for (FunctionType::ParamTypes::const_iterator + I = MTy->getParamTypes().begin(), + E = MTy->getParamTypes().end(); I != E; ++I) { + if (I != MTy->getParamTypes().begin()) + Result += ", "; + MInfo = ""; + Result += calcTypeName(*I, TypeStack, TypeNames, &MInfo); + if (MInfo != "") + Result += ") " + MInfo; + } + if (MTy->isVarArg()) { + if (!MTy->getParamTypes().empty()) + Result += ", "; + Result += "..."; + } + Result += ")"; + break; + } + case Type::StructTyID: { + const StructType *STy = cast(Ty); + Result = " struct {\n "; + int indx = 0; + for (StructType::ElementTypes::const_iterator + I = STy->getElementTypes().begin(), + E = STy->getElementTypes().end(); I != E; ++I) { + Result += calcTypeNameVar(*I, TypeStack, TypeNames, + "field" + itostr(indx++), ""); + Result += ";\n "; + } + Result += " }"; + Result += " " + NameSoFar + VariableName; + break; + } + + case Type::PointerTyID: { + Result = calcTypeNameVar(cast(Ty)->getElementType(), + TypeStack, TypeNames, tempstr, + "(*" + NameSoFar + VariableName + ")"); + break; + } + + case Type::ArrayTyID: { + const ArrayType *ATy = cast(Ty); + int NumElements = ATy->getNumElements(); + Result = calcTypeNameVar(ATy->getElementType(), TypeStack, TypeNames, + tempstr, NameSoFar + VariableName + "[" + + itostr(NumElements) + "]"); + break; + } + default: + assert(0 && "Unhandled case in getTypeProps!"); + Result = ""; + } + + TypeStack.pop_back(); // Remove self from stack... + return Result; +} + +// printTypeVarInt - The internal guts of printing out a type that has a +// potentially named portion and the variable associated with the type. +static ostream &printTypeVarInt(ostream &Out, const Type *Ty, + map &TypeNames, + string VariableName) { + // Primitive types always print out their description, regardless of whether + // they have been named or not. + + // Booleans have to be specially handled to be printed as ints with values + // 0 or 1; + if (Ty->isPrimitiveType()) + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + return Out << "int " << VariableName; + break; + case Type::UByteTyID: + return Out << "unsigned char " << VariableName; + break; + case Type::SByteTyID: + return Out << "signed char " << VariableName; + break; + case Type::UShortTyID: + return Out << "unsigned long long " << VariableName; + break; + case Type::ULongTyID: + return Out << "unsigned long long " << VariableName; + break; + case Type::LongTyID: + return Out << "signed long long " << VariableName; + break; + case Type::UIntTyID: + return Out << "unsigned int " << VariableName; + break; + default : + return Out << Ty->getDescription() << " " << VariableName; + } + + // Check to see if the type is named. + map::iterator I = TypeNames.find(Ty); + if (I != TypeNames.end()) return Out << I->second << " " << VariableName; + + // Otherwise we have a type that has not been named but is a derived type. + // Carefully recurse the type hierarchy to print out any contained symbolic + // names. + // + vector TypeStack; + string TypeNameVar, tempstr = ""; + TypeNameVar = calcTypeNameVar(Ty, TypeStack, TypeNames, VariableName, + tempstr); + return Out << TypeNameVar; + // TODO: Check what happens to caching + // TypeNames.insert(std::make_pair(Ty, TypeName)); + //Cache type name for later use +} + +// Internal guts of printing a type name +static ostream &printTypeInt(ostream &Out, const Type *Ty, + map &TypeNames) { + // Primitive types always print out their description, regardless of whether + // they have been named or not. + + // Booleans have to be specially handled to be printed as ints with values + // 0 or 1; + + if (Ty->isPrimitiveType()) + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + return Out << "int"; + break; + case Type::UByteTyID: + return Out << "unsigned char"; + break; + case Type::SByteTyID: + return Out << "signed char"; + break; + case Type::UShortTyID: + return Out << "unsigned long long"; + break; + case Type::ULongTyID: + return Out << "unsigned long long"; + break; + case Type::LongTyID: + return Out << "signed long long"; + break; + case Type::UIntTyID: + return Out << "unsigned int"; + break; + default : + return Out << Ty->getDescription(); + } + + // Check to see if the type is named. + map::iterator I = TypeNames.find(Ty); + if (I != TypeNames.end()) return Out << I->second; + + // Otherwise we have a type that has not been named but is a derived type. + // Carefully recurse the type hierarchy to print out any contained symbolic + // names. + // + vector TypeStack; + string MInfo = ""; + string TypeName = calcTypeName(Ty, TypeStack, TypeNames, &MInfo); + // TypeNames.insert(std::make_pair(Ty, TypeName)); + //Cache type name for later use + if (MInfo != "") + return Out << TypeName << ")" << MInfo; + else + return Out << TypeName; +} + +namespace { + + //Internal CWriter class mimics AssemblyWriter. + class CWriter { + ostream& Out; + SlotCalculator &Table; + const Module *TheModule; + map TypeNames; + public: + inline CWriter(ostream &o, SlotCalculator &Tab, const Module *M) + : Out(o), Table(Tab), TheModule(M) { + + } + + inline void write(const Module *M) { printModule(M); } + + ostream& printTypeVar(const Type *Ty, string VariableName, ostream &Out); + ostream& printType(const Type *Ty, ostream &Out); + void writeOperand(const Value *Operand, bool PrintType,ostream &Out, + bool PrintName = true); + + private : + void printModule(const Module *M); + void printSymbolTable(const SymbolTable &ST); + void printConstant(const Constant *CPV); + void printGlobal(const GlobalVariable *GV); + void printFunctionDecl(const Function *M); //for printing just the method + // declaration + void printFunctionArgument(const Argument *MA); + + void printFunction(const Function *); + + void outputFunction(const Function *, CLocalVars &); + void outputBasicBlock(const BasicBlock *); + }; + /* END class CWriter */ + + + /* CLASS InstLocalVarsVisitor */ + class InstLocalVarsVisitor : public InstVisitor { + SlotCalculator& Table; + + void handleTerminator(TerminatorInst *tI,int indx); + + public: + CLocalVars CLV; + + InstLocalVarsVisitor(SlotCalculator& table) : Table(table) { + + } + + void visitInstruction(Instruction *I) { + string tempostr; + if (I && I->hasName() && !isa(I)) { + tempostr = "llvm__" + makeNameProper(I->getName()) + "_" + + itostr((int)I->getType()->getUniqueID()); + CLV.addLocalVar(I->getType(), tempostr); + } else if (I) { + int Slot = Table.getValSlot(I); + //if (Slot < 0) then it is a instruction with no + // value (like return void ) + if ((Slot >= 0) && !isa(I)) { + tempostr = "llvm__tmp_"; + tempostr += itostr(Slot) + "_" + + itostr((int)I->getType()->getUniqueID()); + CLV.addLocalVar(I->getType(), tempostr); + } + } + + } + + void visitBranchInst(BranchInst *I) { + TerminatorInst *tI = cast(I); + if (I->getNumOperands() > 1) { + handleTerminator(tI, 0); + handleTerminator(tI, 1); + } + else { + handleTerminator(tI, 0); + } + } + + }; + + + /* CLASS CInstPrintVisitor */ + + class CInstPrintVisitor: public InstVisitor { + CWriter& CW; + SlotCalculator& Table; + ostream &Out; + const Value *Operand; + + void outputLValue(Instruction *); + void printPhiFromNextBlock(TerminatorInst *tI, int indx); + + public: + CInstPrintVisitor (CWriter &cw, SlotCalculator& table, ostream& o) + : CW(cw), Table(table), Out(o) { + + } + + void visitCastInst(CastInst *I); + void visitCallInst(CallInst *I); + void visitShr(ShiftInst *I); + void visitShl(ShiftInst *I); + void visitReturnInst(ReturnInst *I); + void visitBranchInst(BranchInst *I); + void visitSwitchInst(SwitchInst *I); + void visitInvokeInst(InvokeInst *I) ; + void visitMallocInst(MallocInst *I); + void visitAllocaInst(AllocaInst *I); + void visitFreeInst(FreeInst *I); + void visitLoadInst(LoadInst *I); + void visitStoreInst(StoreInst *I); + void visitGetElementPtrInst(GetElementPtrInst *I); + void visitPHINode(PHINode *I); + void visitUnaryOperator (UnaryOperator *I); + void visitBinaryOperator(BinaryOperator *I); + + }; + +} + +void InstLocalVarsVisitor::handleTerminator(TerminatorInst *tI,int indx) { + BasicBlock *bb = tI->getSuccessor(indx); + BasicBlock::const_iterator insIt = bb->begin(); + while (insIt != bb->end()) { + if (const PHINode *pI = dyn_cast(*insIt)) { + //Its a phinode! + //Calculate the incoming index for this + int incindex = pI->getBasicBlockIndex(tI->getParent()); + if (incindex != -1) + if (pI && pI->hasName()) { + string tempostr; + tempostr = "llvm__" + makeNameProper(pI->getName()) + "_" + + itostr((int)pI->getType()->getUniqueID()); + CLV.addLocalVar(pI->getType(), tempostr) ; + } else { + string tempostr; + int Slot = Table.getValSlot(pI); + if (Slot >= 0) { + tempostr = "llvm__tmp_" + itostr(Slot) + "_" + + itostr((int)pI->getType()->getUniqueID()); + CLV.addLocalVar(pI->getType(), tempostr); + } + } + + } + else break; + insIt++; + } +} + +/* Implementation of CInstPrintVisitor */ + +void CInstPrintVisitor::outputLValue(Instruction *I) { + if (I && I->hasName() && !isa(I)) { + Out << "llvm__" << makeNameProper(I->getName()) << "_" + << I->getType()->getUniqueID() << " = "; + } else { + int Slot = Table.getValSlot(I); + //if (Slot < 0) then it is a instruction with no value (like return void ) + if ((Slot >= 0) && !isa(I)) + Out << "llvm__tmp_" << Slot << "_" << I->getType()->getUniqueID() + << " = "; + } +} + +void CInstPrintVisitor::printPhiFromNextBlock(TerminatorInst *tI, int indx) { + BasicBlock *bb = tI->getSuccessor(indx); + BasicBlock::const_iterator insIt = bb->begin(); + while (insIt != bb->end()) { + if (const PHINode *pI = dyn_cast(*insIt)) { + //Its a phinode! + //Calculate the incoming index for this + int incindex = pI->getBasicBlockIndex(tI->getParent()); + if (incindex != -1) + { + //now we have to do the printing + if (pI && pI->hasName()) { + Out << "llvm__" << makeNameProper(pI->getName()) << "_" + << pI->getType()->getUniqueID() << " = "; + } else { + int Slot = Table.getValSlot(pI); + if (Slot >= 0) + Out << "llvm__tmp_" << Slot << "_" + << pI->getType()->getUniqueID() << " = "; + } + CW.writeOperand(pI->getIncomingValue(incindex),false, Out); + Out << ";\n"; + } + } + else break; + insIt++; + } +} + +// Implement all "other" instructions, except for PHINode +void CInstPrintVisitor::visitCastInst(CastInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "("; + CW.printType(I->getType(), Out); + Out << ")"; + CW.writeOperand(Operand, false, Out); + Out << ";\n"; +} + +void CInstPrintVisitor::visitCallInst(CallInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + const PointerType *PTy = dyn_cast(Operand->getType()); + const FunctionType *MTy = PTy + ? dyn_cast(PTy->getElementType()):0; + const Type *RetTy = MTy ? MTy->getReturnType() : 0; + + // If possible, print out the short form of the call instruction, but we can + // only do this if the first argument is a pointer to a nonvararg method, + // and if the value returned is not a pointer to a method. + // + if (RetTy && !MTy->isVarArg() && + (!isa(RetTy)|| + !isa(cast(RetTy)))){ + Out << " "; + Out << makeNameProper(Operand->getName()); + } else { + Out << makeNameProper(Operand->getName()); + } + Out << "("; + if (I->getNumOperands() > 1) + CW.writeOperand(I->getOperand(1), false, Out); + for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; ++op) { + Out << ","; + CW.writeOperand(I->getOperand(op), false, Out); + } + + Out << " );\n"; +} + +void CInstPrintVisitor::visitShr(ShiftInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "("; + CW.writeOperand(Operand, false, Out); + Out << " >> "; + Out << "("; + CW.writeOperand(I->getOperand(1), false, Out); + Out << "));\n"; +} + +void CInstPrintVisitor::visitShl(ShiftInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "("; + CW.writeOperand(Operand, false, Out); + Out << " << "; + Out << "("; + CW.writeOperand(I->getOperand(1), false, Out); + Out << "));\n"; +} + +// Specific Instruction type classes... note that all of the casts are +// neccesary because we use the instruction classes as opaque types... +// +void CInstPrintVisitor::visitReturnInst(ReturnInst *I) { + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "return "; + if (Operand) + CW.writeOperand(Operand,false, Out); + Out << ";\n"; +} + +void CInstPrintVisitor::visitBranchInst(BranchInst *I) { + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + TerminatorInst *tI = cast(I); + if (I->getNumOperands() > 1) { + Out << "if ("; + CW.writeOperand(I->getOperand(2),false, Out); + Out << ") {\n"; + printPhiFromNextBlock(tI,0); + Out << " goto "; + CW.writeOperand(Operand,false, Out); + Out << ";\n"; + Out << "}" << "else {\n"; + printPhiFromNextBlock(tI,1); + Out << " goto "; + CW.writeOperand(I->getOperand(1),false, Out); + Out << ";\n"; + Out << "}\n"; + } else { + printPhiFromNextBlock(tI,0); + Out << " goto "; + CW.writeOperand(Operand, false, Out); + Out << ";\n"; + } + Out << "\n"; +} + +void CInstPrintVisitor::visitSwitchInst(SwitchInst *I) { + Out << "\n"; +} + +void CInstPrintVisitor::visitInvokeInst(InvokeInst *I) { + Out << "\n"; +} + +void CInstPrintVisitor::visitMallocInst(MallocInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + string tempstr = ""; + Out << "("; + CW.printType(cast(I->getType())->getElementType(), Out); + Out << "*) malloc(sizeof("; + CW.printTypeVar(cast(I->getType())->getElementType(), + tempstr, Out); + Out << ")"; + if (I->getNumOperands()) { + Out << " * " ; + CW.writeOperand(Operand, false, Out); + } + Out << ");"; +} + +void CInstPrintVisitor::visitAllocaInst(AllocaInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + string tempstr = ""; + Out << "("; + CW.printTypeVar(I->getType(), tempstr, Out); + Out << ") alloca(sizeof("; + CW.printTypeVar(cast(I->getType())->getElementType(), + tempstr, Out); + Out << ")"; + if (I->getNumOperands()) { + Out << " * " ; + CW.writeOperand(Operand, false, Out); + } + Out << ");\n"; +} + +void CInstPrintVisitor::visitFreeInst(FreeInst *I) { + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "free("; + CW.writeOperand(Operand, false, Out); + Out << ");\n"; +} + +void CInstPrintVisitor::visitLoadInst(LoadInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + if (I->getNumOperands() <= 1) { + Out << "*"; + CW.writeOperand(Operand,false, Out); + } + else { + //Check if it is an array type or struct type ptr! + int arrtype = 1; + const PointerType *PTy = dyn_cast(I->getType()); + if (cast(Operand->getType())->getElementType()->getPrimitiveID() == Type::StructTyID) + arrtype = 0; + if (arrtype && isa(Operand)) + Out << "(&"; + CW.writeOperand(Operand,false, Out); + for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) { + if (i == 1) { + if (arrtype || !isa(Operand)) { + Out << "["; + CW.writeOperand(I->getOperand(i), false, Out); + Out << "]"; + } + if (isa(Operand) && arrtype) + Out << ")"; + } + else { + if (arrtype == 1) Out << "["; + else + Out << ".field"; + CW.writeOperand(I->getOperand(i), false, Out); + if (arrtype == 1) Out << "]"; + } + } + } + Out << ";\n"; +} + +void CInstPrintVisitor::visitStoreInst(StoreInst *I) { + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + if (I->getNumOperands() <= 2) { + Out << "*"; + CW.writeOperand(I->getOperand(1), false, Out); + } + else { + //Check if it is an array type or struct type ptr! + int arrtype = 1; + if (cast(I->getOperand(1)->getType())->getElementType()->getPrimitiveID() == Type::StructTyID) + arrtype = 0; + if (isa(I->getOperand(1)) && arrtype) + Out << "(&"; + CW.writeOperand(I->getOperand(1), false, Out); + for (unsigned i = 2, E = I->getNumOperands(); i != E; ++i) { + if (i == 2) { + if (arrtype || !isa(I->getOperand(1))) { + Out << "["; + CW.writeOperand(I->getOperand(i), false, Out); + Out << "]"; + } + if (isa(I->getOperand(1)) && arrtype) + Out << ")"; + } + else { + if (arrtype == 1) Out << "["; + else + Out << ".field"; + CW.writeOperand(I->getOperand(i), false, Out); + if (arrtype == 1) Out << "]"; + } + } + } + Out << " = "; + CW.writeOperand(Operand,false, Out); + Out << ";\n"; +} + +void CInstPrintVisitor::visitGetElementPtrInst(GetElementPtrInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << " &("; + if (I->getNumOperands() <= 1) + CW.writeOperand(Operand,false, Out); + else { + //Check if it is an array type or struct type ptr! + int arrtype = 1; + if ((cast(Operand->getType()))->getElementType()->getPrimitiveID() == Type::StructTyID) + arrtype = 0; + if ((isa(Operand)) && arrtype) + Out << "(&"; + CW.writeOperand(Operand,false, Out); + for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) { + if (i == 1) { + if (arrtype || !isa(Operand)){ + Out << "["; + CW.writeOperand(I->getOperand(i), false, Out); + Out << "]"; + } + if (isa(Operand) && arrtype) + Out << ")"; + } + else { + if (arrtype == 1) Out << "["; + else + Out << ".field"; + CW.writeOperand(I->getOperand(i), false, Out); + if (arrtype == 1) Out << "]"; + } + } + } + Out << ");\n"; +} + +void CInstPrintVisitor::visitPHINode(PHINode *I) { + +} + +void CInstPrintVisitor::visitUnaryOperator (UnaryOperator *I) { + if (I->getOpcode() == Instruction::Not) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "!("; + CW.writeOperand(Operand,false, Out); + Out << ");\n"; + } + else { + Out << "\n"; + } +} + +void CInstPrintVisitor::visitBinaryOperator(BinaryOperator *I) { + //binary instructions, shift instructions, setCond instructions. + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + if (I->getType()->getPrimitiveID() == Type::PointerTyID) { + Out << "("; + CW.printType(I->getType(), Out); + Out << ")"; + } + Out << "("; + if (Operand->getType()->getPrimitiveID() == Type::PointerTyID) + Out << "(long long)"; + CW.writeOperand(Operand,false, Out); + Out << getOpcodeOperName(I); + // Need the extra parenthisis if the second operand is < 0 + Out << '('; + if (I->getOperand(1)->getType()->getPrimitiveID() == Type::PointerTyID) + Out << "(long long)"; + CW.writeOperand(I->getOperand(1),false, Out); + Out << ')'; + Out << ");\n"; +} + +/* END : CInstPrintVisitor implementation */ + +void CWriter::printModule(const Module *M) { + // printing stdlib inclusion + // Out << "#include \n"; + + // Loop over the symbol table, emitting all named constants... + if (M->hasSymbolTable()) + printSymbolTable(*M->getSymbolTable()); + + for_each(M->gbegin(), M->gend(), + bind_obj(this, &CWriter::printGlobal)); + + // First output all the declarations of the methods as C requires Functions + // be declared before they are used. + for_each(M->begin(), M->end(), bind_obj(this,&CWriter::printFunctionDecl)); + + // declaration of alloca + Out << "void *alloca(unsigned long size);\n"; + + // Output all of the methods... + for_each(M->begin(), M->end(), bind_obj(this,&CWriter::printFunction)); +} + +// prints the global constants +void CWriter::printGlobal(const GlobalVariable *GV) { + string tempostr; + if (GV->hasName()) + tempostr = "llvm__" + makeNameProper(GV->getName()) + "_" + + itostr((int)GV->getType()->getUniqueID()); + if (GV->hasInternalLinkage()) Out << "static "; + + printTypeVar(GV->getType()->getElementType(), tempostr, Out); + + if (GV->hasInitializer()) { + Out << " = " ; + writeOperand(GV->getInitializer(), false, Out, false); + } + + Out << ";\n"; +} + +// printSymbolTable - Run through symbol table looking for named constants +// if a named constant is found, emit it's declaration... +// Assuming that symbol table has only types and constants. +void CWriter::printSymbolTable(const SymbolTable &ST) { + // GraphT G; + for (SymbolTable::const_iterator TI = ST.begin(); TI != ST.end(); ++TI) { + SymbolTable::type_const_iterator I = ST.type_begin(TI->first); + SymbolTable::type_const_iterator End = ST.type_end(TI->first); + + // TODO + // Need to run through all the used types in the program + // FindUsedTypes &FUT = new FindUsedTypes(); + // const std::set &UsedTypes = FUT.getTypes(); + // Filter out the structures printing forward definitions for each of them + // and creating the dependency graph. + // Print forward definitions to all of them + // print the typedefs topologically sorted + + // But for now we have + for (; I != End; ++I) { + const Value *V = I->second; + if (const Constant *CPV = dyn_cast(V)) { + printConstant(CPV); + } else if (const Type *Ty = dyn_cast(V)) { + string tempostr; + string tempstr = ""; + Out << "typedef "; + vector TypeStack; + tempostr = "llvm__" + I->first; + string TypeNameVar = calcTypeNameVar(Ty, TypeStack, TypeNames, + tempostr, tempstr); + Out << TypeNameVar << ";\n"; + if (!isa(Ty) || + !cast(Ty)->getElementType()->isPrimitiveType()) + TypeNames.insert(std::make_pair(Ty, "llvm__"+I->first)); + } + } + } +} + + +// printConstant - Print out a constant pool entry... +// +void CWriter::printConstant(const Constant *CPV) { + // TODO + // Dinakar : Don't know what to do with unnamed constants + // should do something about it later. + + string tempostr; + if (CPV->hasName()) { + // Print out name... + tempostr = "llvm__" + makeNameProper(CPV->getName()) + "_" + + itostr((int)CPV->getType()->getUniqueID()); + } else { + int Slot = Table.getValSlot(CPV); // slot number + if (Slot >= 0) + tempostr = "llvm__tmp_" + itostr(Slot) + "_" + + itostr((int)CPV->getType()->getUniqueID()); + else + tempostr = ""; + } + + // Print out the constant type... + printTypeVar(CPV->getType(), tempostr, Out); + + Out << " = "; + // Write the value out now... + writeOperand(CPV, false, Out, false); + + Out << "\n"; +} + + + +// printFunctionDecl - Print method declaration +// +void CWriter::printFunctionDecl(const Function *M) { + + if (M->hasInternalLinkage()) Out <<"static "; + + // Loop over the arguments, printing them... + const FunctionType *MT = cast(M->getFunctionType()); + + if (!M->isExternal()) { + // Print out the return type and name... + printType(M->getReturnType(), Out); + Out << " " << makeNameProper(M->getName()) << "("; + + for_each(M->getArgumentList().begin(), M->getArgumentList().end(), + bind_obj(this, &CWriter::printFunctionArgument)); + } else { + // Print out the return type and name... + printType(M->getReturnType(), Out) ; + Out << " " << makeNameProper(M->getName()) << "("; + + // Loop over the arguments, printing them... + const FunctionType *MT = cast(M->getFunctionType()); + for (FunctionType::ParamTypes::const_iterator I = + MT->getParamTypes().begin(), + E = MT->getParamTypes().end(); I != E; ++I) { + if (I != MT->getParamTypes().begin()) Out << ", "; + printType(*I, Out); + } + } + + // Finish printing arguments... + if (MT->isVarArg()) { + if (MT->getParamTypes().size()) Out << ", "; + Out << "..."; // Output varargs portion of signature! + } + Out << ");\n"; +} + +void CWriter::printFunction(const Function *M) { + if (!M->isExternal()) { + // Process each of the basic blocks, gather information and call the + // output methods on the CLocalVars and Function* objects. + + // gather local variable information for each basic block + InstLocalVarsVisitor ILV(Table); + ILV.visit((Function *)M); + + // Spout out code. + outputFunction(M, ILV.CLV); + + } +} + +// printFunctionArgument - This member is called for every argument that +// is passed into the method. Simply print it out +// +void CWriter::printFunctionArgument(const Argument *Arg) { + // Insert commas as we go... the first arg doesn't get a comma + string tempostr; + if (Arg != Arg->getParent()->getArgumentList().front()) Out << ", "; + + // Output name, if available... + if (Arg->hasName()) { + tempostr = "llvm__" + makeNameProper(Arg->getName()) + "_" + + itostr((int)Arg->getType()->getUniqueID()); + } else if (Table.getValSlot(Arg) < 0) { + tempostr = ""; + } + else { + tempostr = "llvm__tmp_" + itostr(Table.getValSlot(Arg)) + "_" + + itostr((int)Arg->getType()->getUniqueID()); + } + // Output type... + // printType(Arg->getType(), Out); + // Out << " " << tempostr; + printTypeVar (Arg->getType(), tempostr, Out); +} + +void CWriter::outputFunction(const Function *M, CLocalVars& CLV) { + // Currently we have a no-loop-structure implementation + // Seems like its not really necessary. + + // Print out the return type and name... + printType(M->getReturnType(), Out) ; + Out << " " << makeNameProper(M->getName()) << "("; + // Loop over the arguments, printing them... + const FunctionType *MT = cast(M->getFunctionType()); + + if (!M->isExternal()) { + for_each(M->getArgumentList().begin(), M->getArgumentList().end(), + bind_obj(this, &CWriter::printFunctionArgument)); + } else { + // Loop over the arguments, printing them... + const FunctionType *MT = cast(M->getFunctionType()); + for (FunctionType::ParamTypes::const_iterator I = + MT->getParamTypes().begin(), + E = MT->getParamTypes().end(); I != E; ++I) { + if (I != MT->getParamTypes().begin()) Out << ", "; + printType(*I, Out); + } + } + + // Finish printing arguments... + if (MT->isVarArg()) { + if (MT->getParamTypes().size()) Out << ", "; + Out << "..."; // Output varargs portion of signature! + } + Out << ")\n"; + + if (!M->isExternal()) { + Out << "{\n"; + // Loop over the symbol table, emitting all named constants... + if (M->hasSymbolTable()) + printSymbolTable(*M->getSymbolTable()); + + // print the local variables + // we assume that every local variable is alloca'ed in the C code. + std::map locals; + locals = CLV.LocalVars; + + map::iterator iter; + for (iter = locals.begin(); iter != locals.end(); iter++) { + VarListType::iterator listiter; + for (listiter = iter->second.begin(); listiter != iter->second.end(); + listiter++) { + // printType(iter->first, Out); + // Out << " " << *listiter << ";\n"; + printTypeVar(iter->first, *listiter, Out); + Out << ";\n"; + } + } + + // print the basic blocks + Function::const_iterator iterBB; + for (iterBB = M->begin(); iterBB != M->end(); ++iterBB) + outputBasicBlock(*iterBB); + + Out << "}\n"; + } +} + +void CWriter::outputBasicBlock(const BasicBlock* BB) { + + if (BB->hasName()) { // Print out the label if it exists... + Out << "llvm__" << makeNameProper(BB->getName()) << "_" + << BB->getType()->getUniqueID() << ":\n"; + } else { + int Slot = Table.getValSlot(BB); + Out << "llvm__tmp_"; + if (Slot >= 0) + Out << Slot << "_" << BB->getType()->getUniqueID() << ":\n"; + // Extra newline seperates out label's + else + Out << "\n"; + } + + // Output all of the instructions in the basic block... + // print the basic blocks + CInstPrintVisitor CIPV(*this, Table, Out); + CIPV.visit((BasicBlock *) BB); +} + +// printTypeVar - Go to extreme measures to attempt to print out a short, +// symbolic version of a type name. +// +ostream& CWriter::printTypeVar(const Type *Ty, string VariableName, + ostream &Out) { + return printTypeVarInt(Out, Ty, TypeNames, VariableName); +} + +// printType - Go to extreme measures to attempt to print out a short, symbolic +// version of a type name. +ostream& CWriter::printType(const Type *Ty, ostream &Out) { + return printTypeInt(Out, Ty, TypeNames); +} + + +void CWriter::writeOperand(const Value *Operand, bool PrintType, + ostream &Out, bool PrintName = true) { + if (PrintType){ + string tempstr = ""; + Out << " "; + printType(Operand->getType(), Out); + } + vector TypeStack; + string MInfo = ""; + string OperandType = calcTypeName(Operand->getType(), TypeStack, TypeNames, + &MInfo); + if (MInfo != "") + OperandType += ")" + MInfo; + WriteCOperandInternal(Out, Operand, PrintName, &Table, OperandType); +} + + +//===----------------------------------------------------------------------===// +// External Interface declaration +//===----------------------------------------------------------------------===// + + +void WriteToC(const Module *C, ostream &Out) { + assert(C && "You can't write a null module!!"); + SlotCalculator SlotTable(C, true); + CWriter W(Out, SlotTable, C); + W.write(C); + Out.flush(); +} + diff --git a/lib/Target/CBackend/Makefile b/lib/Target/CBackend/Makefile new file mode 100644 index 0000000000..3c08fe0da9 --- /dev/null +++ b/lib/Target/CBackend/Makefile @@ -0,0 +1,7 @@ + +LEVEL = ../.. + +LIBRARYNAME = cwriter + +include $(LEVEL)/Makefile.common + diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp new file mode 100644 index 0000000000..02d470cf3f --- /dev/null +++ b/lib/Target/CBackend/Writer.cpp @@ -0,0 +1,1415 @@ +//===-- Writer.cpp - Library for writing C files -----------------*- C++ -*--=// +// +// This library implements the functionality defined in llvm/Assembly/CWriter.h +// and CLocalVars.h +// +// TODO : Recursive types. +//===-----------------------------------------------------------------------==// +#include "llvm/Assembly/CWriter.h" +#include "CLocalVars.h" +#include "llvm/SlotCalculator.h" +#include "llvm/Module.h" +#include "llvm/Argument.h" +#include "llvm/Function.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Constants.h" +#include "llvm/GlobalVariable.h" +#include "llvm/BasicBlock.h" +#include "llvm/iMemory.h" +#include "llvm/iTerminators.h" +#include "llvm/iPHINode.h" +#include "llvm/iOther.h" +#include "llvm/SymbolTable.h" +#include "llvm/Support/InstVisitor.h" +#include "Support/StringExtras.h" +#include "Support/STLExtras.h" + +#include +#include +using std::string; +using std::map; +using std::vector; +using std::ostream; + +/* Implementation of the CLocalVars methods */ + +// Appends a variable to the LocalVars map if it does not already exist +// Also check that the type exists on the map. +void CLocalVars::addLocalVar(const Type *t, const string & var) { + if (!LocalVars.count(t) || + find(LocalVars[t].begin(), LocalVars[t].end(), var) + == LocalVars[t].end()) { + LocalVars[t].push_back(var); + } +} + +/* Writer.cpp */ +static string calcTypeNameVar(const Type *Ty, vector &TypeStack, + map &TypeNames, + string VariableName, string NameSoFar); + +static std::string getConstStrValue(const Constant* CPV); + + +// +//Getting opcodes in terms of the operator +// +static const char *getOpcodeOperName(const Instruction *I) { + switch (I->getOpcode()) { + // Standard binary operators... + case Instruction::Add: return "+"; + case Instruction::Sub: return "-"; + case Instruction::Mul: return "*"; + case Instruction::Div: return "/"; + case Instruction::Rem: return "%"; + + // Logical operators... + case Instruction::And: return "&"; + case Instruction::Or: return "|"; + case Instruction::Xor: return "^"; + + // SetCond operators... + case Instruction::SetEQ: return "=="; + case Instruction::SetNE: return "!="; + case Instruction::SetLE: return "<="; + case Instruction::SetGE: return ">="; + case Instruction::SetLT: return "<"; + case Instruction::SetGT: return ">"; + + //ShiftInstruction... + + case Instruction::Shl : return "<<"; + case Instruction::Shr : return ">>"; + + default: + cerr << "Invalid operator type!" << I->getOpcode() << "\n"; + abort(); + } + return 0; +} + + +// We dont want identifier names with ., space, - in them. +// So we replace them with _ +static string makeNameProper(string x) { + string tmp; + for (string::iterator sI = x.begin(), sEnd = x.end(); sI != sEnd; sI++) { + if (*sI == '.') + tmp += '_'; + else if (*sI == ' ') + tmp += '_'; + else if (*sI == '-') + tmp += "__"; + else + tmp += *sI; + } + return tmp; +} + +static string getConstantName(const Constant *CPV) { + return CPV->getName(); +} + + +static std::string getConstArrayStrValue(const Constant* CPV) { + std::string Result; + + // As a special case, print the array as a string if it is an array of + // ubytes or an array of sbytes with positive values. + // + const Type *ETy = cast(CPV->getType())->getElementType(); + bool isString = (ETy == Type::SByteTy || ETy == Type::UByteTy); + + if (ETy == Type::SByteTy) { + for (unsigned i = 0; i < CPV->getNumOperands(); ++i) + if (ETy == Type::SByteTy && + cast(CPV->getOperand(i))->getValue() < 0) { + isString = false; + break; + } + } + + if (isString) { + Result = "\""; + for (unsigned i = 0; i < CPV->getNumOperands(); ++i) { + unsigned char C = (ETy == Type::SByteTy) ? + (unsigned char)cast(CPV->getOperand(i))->getValue() : + (unsigned char)cast(CPV->getOperand(i))->getValue(); + + if (isprint(C)) { + Result += C; + } else { + Result += '\\'; + Result += 'x'; + Result += ( C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A'); + Result += ((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'); + } + } + Result += "\""; + + } else { + Result = "{"; + if (CPV->getNumOperands()) { + Result += " " + getConstStrValue(cast(CPV->getOperand(0))); + for (unsigned i = 1; i < CPV->getNumOperands(); i++) + Result += ", " + getConstStrValue(cast(CPV->getOperand(i))); + } + Result += " }"; + } + + return Result; +} + +static std::string getConstStructStrValue(const Constant* CPV) { + std::string Result = "{"; + if (CPV->getNumOperands()) { + Result += " " + getConstStrValue(cast(CPV->getOperand(0))); + for (unsigned i = 1; i < CPV->getNumOperands(); i++) + Result += ", " + getConstStrValue(cast(CPV->getOperand(i))); + } + + return Result + " }"; +} + +// our own getStrValue function for constant initializers +static std::string getConstStrValue(const Constant* CPV) { + // Does not handle null pointers, that needs to be checked explicitly + string tempstr; + if (CPV == ConstantBool::False) + return "0"; + else if (CPV == ConstantBool::True) + return "1"; + + else if (isa(CPV)) { + tempstr = getConstArrayStrValue(CPV); + } + else if (isa(CPV)) { + tempstr = getConstStructStrValue(CPV); + } + else if (ConstantUInt *CUI = dyn_cast(CPV)) { + tempstr = utostr((long long unsigned int) CUI->getValue()); + } + else if (ConstantSInt *CSI = dyn_cast(CPV)) { + tempstr = itostr(CSI->getValue()); + } + else if (ConstantFP *CFP = dyn_cast(CPV)) { + tempstr = ftostr(CFP->getValue()); + } + + if (CPV->getType() == Type::ULongTy) + tempstr += "ull"; + else if (CPV->getType() == Type::LongTy) + tempstr += "ll"; + else if (CPV->getType() == Type::UIntTy || + CPV->getType() == Type::UShortTy) + tempstr += "u"; + + return tempstr; + +} + +// WriteCOperand - Write the name of the specified value out to the specified +// ostream. This can be useful when you just want to print int %0 not the +// whole instruction that generated it. +// +static void WriteCOperandInternal(ostream &Out, const Value *V, + bool PrintName, SlotCalculator *Table, + string &OperandType) { + int Slot; + if (PrintName && V->hasName()) { + // If V has a name. + Out << "llvm__" << makeNameProper(V->getName()) << "_" << + (V->getType())->getUniqueID(); + return; + } + else if (const Constant *CPV = dyn_cast(V)) { + if (isa(CPV)) { + Out << "(" << OperandType << ")0"; + } + else + Out << getConstStrValue(CPV); + } + else { + Slot = Table->getValSlot(V); + if (Slot >= 0) + Out << "llvm__tmp_" << Slot << "_" << V->getType()->getUniqueID(); + else if (PrintName) + Out << ""; + } +} + +// Internal function +// Essentially pass the Type* variable, an empty typestack and this prints +// out the C type +static string calcTypeName(const Type *Ty, vector &TypeStack, + map &TypeNames, + string *FunctionInfo) { + + // Takin' care of the fact that boolean would be int in C + // and that ushort would be unsigned short etc. + + // Base Case + if (Ty->isPrimitiveType()) + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + return "int"; + break; + case Type::UByteTyID: + return "unsigned char"; + break; + case Type::SByteTyID: + return "signed char"; + break; + case Type::UShortTyID: + return "unsigned long long"; + break; + case Type::ULongTyID: + return "unsigned long long"; + break; + case Type::LongTyID: + return "signed long long"; + break; + case Type::UIntTyID: + return "unsigned int"; + break; + default : + return Ty->getDescription(); + } + + // Check to see if the type is named. + map::iterator I = TypeNames.find(Ty); + if (I != TypeNames.end()) + return I->second; + + // Check to see if the Type is already on the stack... + unsigned Slot = 0, CurSize = TypeStack.size(); + while (Slot < CurSize && TypeStack[Slot] != Ty) ++Slot; // Scan for type + + // This is another base case for the recursion. In this case, we know + // that we have looped back to a type that we have previously visited. + // Generate the appropriate upreference to handle this. + // + if (Slot < CurSize) + return "\\" + utostr(CurSize-Slot); // Here's the upreference + + TypeStack.push_back(Ty); // Recursive case: Add us to the stack.. + + string Result; + string MInfo = ""; + switch (Ty->getPrimitiveID()) { + case Type::FunctionTyID: { + const FunctionType *MTy = cast(Ty); + Result = calcTypeName(MTy->getReturnType(), TypeStack, TypeNames, &MInfo); + if (MInfo != "") + Result += ") " + MInfo; + Result += "("; + *FunctionInfo += " ("; + for (FunctionType::ParamTypes::const_iterator + I = MTy->getParamTypes().begin(), + E = MTy->getParamTypes().end(); I != E; ++I) { + if (I != MTy->getParamTypes().begin()) + *FunctionInfo += ", "; + MInfo = ""; + *FunctionInfo += calcTypeName(*I, TypeStack, TypeNames, &MInfo); + if (MInfo != "") + Result += ") " + MInfo; + } + if (MTy->isVarArg()) { + if (!MTy->getParamTypes().empty()) + *FunctionInfo += ", "; + *FunctionInfo += "..."; + } + *FunctionInfo += ")"; + break; + } + case Type::StructTyID: { + string tempstr = ""; + const StructType *STy = cast(Ty); + Result = " struct {\n "; + int indx = 0; + for (StructType::ElementTypes::const_iterator + I = STy->getElementTypes().begin(), + E = STy->getElementTypes().end(); I != E; ++I) { + Result += calcTypeNameVar(*I, TypeStack, TypeNames, + "field" + itostr(indx++), tempstr); + Result += ";\n "; + } + Result += " } "; + break; + } + case Type::PointerTyID: + Result = calcTypeName(cast(Ty)->getElementType(), + TypeStack, TypeNames, &MInfo); + Result += "*"; + break; + case Type::ArrayTyID: { + const ArrayType *ATy = cast(Ty); + int NumElements = ATy->getNumElements(); + Result = calcTypeName(ATy->getElementType(), TypeStack, TypeNames, &MInfo); + Result += "*"; + break; + } + default: + assert(0 && "Unhandled case in getTypeProps!"); + Result = ""; + } + + TypeStack.pop_back(); // Remove self from stack... + return Result; +} + +// Internal function +// Pass the Type* variable and and the variable name and this prints out the +// variable declaration. +// This is different from calcTypeName because if you need to declare an array +// the size of the array would appear after the variable name itself +// For eg. int a[10]; +static string calcTypeNameVar(const Type *Ty, vector &TypeStack, + map &TypeNames, + string VariableName, string NameSoFar) { + if (Ty->isPrimitiveType()) + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + return "int " + NameSoFar + VariableName; + break; + case Type::UByteTyID: + return "unsigned char " + NameSoFar + VariableName; + break; + case Type::SByteTyID: + return "signed char " + NameSoFar + VariableName; + break; + case Type::UShortTyID: + return "unsigned long long " + NameSoFar + VariableName; + break; + case Type::ULongTyID: + return "unsigned long long " + NameSoFar + VariableName; + break; + case Type::LongTyID: + return "signed long long " + NameSoFar + VariableName; + break; + case Type::UIntTyID: + return "unsigned int " + NameSoFar + VariableName; + break; + default : + return Ty->getDescription() + " " + NameSoFar + VariableName; + } + + // Check to see if the type is named. + map::iterator I = TypeNames.find(Ty); + if (I != TypeNames.end()) + return I->second + " " + NameSoFar + VariableName; + + // Check to see if the Type is already on the stack... + unsigned Slot = 0, CurSize = TypeStack.size(); + while (Slot < CurSize && TypeStack[Slot] != Ty) ++Slot; // Scan for type + + if (Slot < CurSize) + return "\\" + utostr(CurSize-Slot) + " " + NameSoFar + VariableName; + // Here's the upreference + + TypeStack.push_back(Ty); // Recursive case: Add us to the stack.. + + string Result; + string tempstr = ""; + + switch (Ty->getPrimitiveID()) { + case Type::FunctionTyID: { + string MInfo = ""; + const FunctionType *MTy = cast(Ty); + Result += calcTypeName(MTy->getReturnType(), TypeStack, TypeNames, &MInfo); + if (MInfo != "") + Result += ") " + MInfo; + Result += " " + NameSoFar + VariableName; + Result += " ("; + for (FunctionType::ParamTypes::const_iterator + I = MTy->getParamTypes().begin(), + E = MTy->getParamTypes().end(); I != E; ++I) { + if (I != MTy->getParamTypes().begin()) + Result += ", "; + MInfo = ""; + Result += calcTypeName(*I, TypeStack, TypeNames, &MInfo); + if (MInfo != "") + Result += ") " + MInfo; + } + if (MTy->isVarArg()) { + if (!MTy->getParamTypes().empty()) + Result += ", "; + Result += "..."; + } + Result += ")"; + break; + } + case Type::StructTyID: { + const StructType *STy = cast(Ty); + Result = " struct {\n "; + int indx = 0; + for (StructType::ElementTypes::const_iterator + I = STy->getElementTypes().begin(), + E = STy->getElementTypes().end(); I != E; ++I) { + Result += calcTypeNameVar(*I, TypeStack, TypeNames, + "field" + itostr(indx++), ""); + Result += ";\n "; + } + Result += " }"; + Result += " " + NameSoFar + VariableName; + break; + } + + case Type::PointerTyID: { + Result = calcTypeNameVar(cast(Ty)->getElementType(), + TypeStack, TypeNames, tempstr, + "(*" + NameSoFar + VariableName + ")"); + break; + } + + case Type::ArrayTyID: { + const ArrayType *ATy = cast(Ty); + int NumElements = ATy->getNumElements(); + Result = calcTypeNameVar(ATy->getElementType(), TypeStack, TypeNames, + tempstr, NameSoFar + VariableName + "[" + + itostr(NumElements) + "]"); + break; + } + default: + assert(0 && "Unhandled case in getTypeProps!"); + Result = ""; + } + + TypeStack.pop_back(); // Remove self from stack... + return Result; +} + +// printTypeVarInt - The internal guts of printing out a type that has a +// potentially named portion and the variable associated with the type. +static ostream &printTypeVarInt(ostream &Out, const Type *Ty, + map &TypeNames, + string VariableName) { + // Primitive types always print out their description, regardless of whether + // they have been named or not. + + // Booleans have to be specially handled to be printed as ints with values + // 0 or 1; + if (Ty->isPrimitiveType()) + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + return Out << "int " << VariableName; + break; + case Type::UByteTyID: + return Out << "unsigned char " << VariableName; + break; + case Type::SByteTyID: + return Out << "signed char " << VariableName; + break; + case Type::UShortTyID: + return Out << "unsigned long long " << VariableName; + break; + case Type::ULongTyID: + return Out << "unsigned long long " << VariableName; + break; + case Type::LongTyID: + return Out << "signed long long " << VariableName; + break; + case Type::UIntTyID: + return Out << "unsigned int " << VariableName; + break; + default : + return Out << Ty->getDescription() << " " << VariableName; + } + + // Check to see if the type is named. + map::iterator I = TypeNames.find(Ty); + if (I != TypeNames.end()) return Out << I->second << " " << VariableName; + + // Otherwise we have a type that has not been named but is a derived type. + // Carefully recurse the type hierarchy to print out any contained symbolic + // names. + // + vector TypeStack; + string TypeNameVar, tempstr = ""; + TypeNameVar = calcTypeNameVar(Ty, TypeStack, TypeNames, VariableName, + tempstr); + return Out << TypeNameVar; + // TODO: Check what happens to caching + // TypeNames.insert(std::make_pair(Ty, TypeName)); + //Cache type name for later use +} + +// Internal guts of printing a type name +static ostream &printTypeInt(ostream &Out, const Type *Ty, + map &TypeNames) { + // Primitive types always print out their description, regardless of whether + // they have been named or not. + + // Booleans have to be specially handled to be printed as ints with values + // 0 or 1; + + if (Ty->isPrimitiveType()) + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: + return Out << "int"; + break; + case Type::UByteTyID: + return Out << "unsigned char"; + break; + case Type::SByteTyID: + return Out << "signed char"; + break; + case Type::UShortTyID: + return Out << "unsigned long long"; + break; + case Type::ULongTyID: + return Out << "unsigned long long"; + break; + case Type::LongTyID: + return Out << "signed long long"; + break; + case Type::UIntTyID: + return Out << "unsigned int"; + break; + default : + return Out << Ty->getDescription(); + } + + // Check to see if the type is named. + map::iterator I = TypeNames.find(Ty); + if (I != TypeNames.end()) return Out << I->second; + + // Otherwise we have a type that has not been named but is a derived type. + // Carefully recurse the type hierarchy to print out any contained symbolic + // names. + // + vector TypeStack; + string MInfo = ""; + string TypeName = calcTypeName(Ty, TypeStack, TypeNames, &MInfo); + // TypeNames.insert(std::make_pair(Ty, TypeName)); + //Cache type name for later use + if (MInfo != "") + return Out << TypeName << ")" << MInfo; + else + return Out << TypeName; +} + +namespace { + + //Internal CWriter class mimics AssemblyWriter. + class CWriter { + ostream& Out; + SlotCalculator &Table; + const Module *TheModule; + map TypeNames; + public: + inline CWriter(ostream &o, SlotCalculator &Tab, const Module *M) + : Out(o), Table(Tab), TheModule(M) { + + } + + inline void write(const Module *M) { printModule(M); } + + ostream& printTypeVar(const Type *Ty, string VariableName, ostream &Out); + ostream& printType(const Type *Ty, ostream &Out); + void writeOperand(const Value *Operand, bool PrintType,ostream &Out, + bool PrintName = true); + + private : + void printModule(const Module *M); + void printSymbolTable(const SymbolTable &ST); + void printConstant(const Constant *CPV); + void printGlobal(const GlobalVariable *GV); + void printFunctionDecl(const Function *M); //for printing just the method + // declaration + void printFunctionArgument(const Argument *MA); + + void printFunction(const Function *); + + void outputFunction(const Function *, CLocalVars &); + void outputBasicBlock(const BasicBlock *); + }; + /* END class CWriter */ + + + /* CLASS InstLocalVarsVisitor */ + class InstLocalVarsVisitor : public InstVisitor { + SlotCalculator& Table; + + void handleTerminator(TerminatorInst *tI,int indx); + + public: + CLocalVars CLV; + + InstLocalVarsVisitor(SlotCalculator& table) : Table(table) { + + } + + void visitInstruction(Instruction *I) { + string tempostr; + if (I && I->hasName() && !isa(I)) { + tempostr = "llvm__" + makeNameProper(I->getName()) + "_" + + itostr((int)I->getType()->getUniqueID()); + CLV.addLocalVar(I->getType(), tempostr); + } else if (I) { + int Slot = Table.getValSlot(I); + //if (Slot < 0) then it is a instruction with no + // value (like return void ) + if ((Slot >= 0) && !isa(I)) { + tempostr = "llvm__tmp_"; + tempostr += itostr(Slot) + "_" + + itostr((int)I->getType()->getUniqueID()); + CLV.addLocalVar(I->getType(), tempostr); + } + } + + } + + void visitBranchInst(BranchInst *I) { + TerminatorInst *tI = cast(I); + if (I->getNumOperands() > 1) { + handleTerminator(tI, 0); + handleTerminator(tI, 1); + } + else { + handleTerminator(tI, 0); + } + } + + }; + + + /* CLASS CInstPrintVisitor */ + + class CInstPrintVisitor: public InstVisitor { + CWriter& CW; + SlotCalculator& Table; + ostream &Out; + const Value *Operand; + + void outputLValue(Instruction *); + void printPhiFromNextBlock(TerminatorInst *tI, int indx); + + public: + CInstPrintVisitor (CWriter &cw, SlotCalculator& table, ostream& o) + : CW(cw), Table(table), Out(o) { + + } + + void visitCastInst(CastInst *I); + void visitCallInst(CallInst *I); + void visitShr(ShiftInst *I); + void visitShl(ShiftInst *I); + void visitReturnInst(ReturnInst *I); + void visitBranchInst(BranchInst *I); + void visitSwitchInst(SwitchInst *I); + void visitInvokeInst(InvokeInst *I) ; + void visitMallocInst(MallocInst *I); + void visitAllocaInst(AllocaInst *I); + void visitFreeInst(FreeInst *I); + void visitLoadInst(LoadInst *I); + void visitStoreInst(StoreInst *I); + void visitGetElementPtrInst(GetElementPtrInst *I); + void visitPHINode(PHINode *I); + void visitUnaryOperator (UnaryOperator *I); + void visitBinaryOperator(BinaryOperator *I); + + }; + +} + +void InstLocalVarsVisitor::handleTerminator(TerminatorInst *tI,int indx) { + BasicBlock *bb = tI->getSuccessor(indx); + BasicBlock::const_iterator insIt = bb->begin(); + while (insIt != bb->end()) { + if (const PHINode *pI = dyn_cast(*insIt)) { + //Its a phinode! + //Calculate the incoming index for this + int incindex = pI->getBasicBlockIndex(tI->getParent()); + if (incindex != -1) + if (pI && pI->hasName()) { + string tempostr; + tempostr = "llvm__" + makeNameProper(pI->getName()) + "_" + + itostr((int)pI->getType()->getUniqueID()); + CLV.addLocalVar(pI->getType(), tempostr) ; + } else { + string tempostr; + int Slot = Table.getValSlot(pI); + if (Slot >= 0) { + tempostr = "llvm__tmp_" + itostr(Slot) + "_" + + itostr((int)pI->getType()->getUniqueID()); + CLV.addLocalVar(pI->getType(), tempostr); + } + } + + } + else break; + insIt++; + } +} + +/* Implementation of CInstPrintVisitor */ + +void CInstPrintVisitor::outputLValue(Instruction *I) { + if (I && I->hasName() && !isa(I)) { + Out << "llvm__" << makeNameProper(I->getName()) << "_" + << I->getType()->getUniqueID() << " = "; + } else { + int Slot = Table.getValSlot(I); + //if (Slot < 0) then it is a instruction with no value (like return void ) + if ((Slot >= 0) && !isa(I)) + Out << "llvm__tmp_" << Slot << "_" << I->getType()->getUniqueID() + << " = "; + } +} + +void CInstPrintVisitor::printPhiFromNextBlock(TerminatorInst *tI, int indx) { + BasicBlock *bb = tI->getSuccessor(indx); + BasicBlock::const_iterator insIt = bb->begin(); + while (insIt != bb->end()) { + if (const PHINode *pI = dyn_cast(*insIt)) { + //Its a phinode! + //Calculate the incoming index for this + int incindex = pI->getBasicBlockIndex(tI->getParent()); + if (incindex != -1) + { + //now we have to do the printing + if (pI && pI->hasName()) { + Out << "llvm__" << makeNameProper(pI->getName()) << "_" + << pI->getType()->getUniqueID() << " = "; + } else { + int Slot = Table.getValSlot(pI); + if (Slot >= 0) + Out << "llvm__tmp_" << Slot << "_" + << pI->getType()->getUniqueID() << " = "; + } + CW.writeOperand(pI->getIncomingValue(incindex),false, Out); + Out << ";\n"; + } + } + else break; + insIt++; + } +} + +// Implement all "other" instructions, except for PHINode +void CInstPrintVisitor::visitCastInst(CastInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "("; + CW.printType(I->getType(), Out); + Out << ")"; + CW.writeOperand(Operand, false, Out); + Out << ";\n"; +} + +void CInstPrintVisitor::visitCallInst(CallInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + const PointerType *PTy = dyn_cast(Operand->getType()); + const FunctionType *MTy = PTy + ? dyn_cast(PTy->getElementType()):0; + const Type *RetTy = MTy ? MTy->getReturnType() : 0; + + // If possible, print out the short form of the call instruction, but we can + // only do this if the first argument is a pointer to a nonvararg method, + // and if the value returned is not a pointer to a method. + // + if (RetTy && !MTy->isVarArg() && + (!isa(RetTy)|| + !isa(cast(RetTy)))){ + Out << " "; + Out << makeNameProper(Operand->getName()); + } else { + Out << makeNameProper(Operand->getName()); + } + Out << "("; + if (I->getNumOperands() > 1) + CW.writeOperand(I->getOperand(1), false, Out); + for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; ++op) { + Out << ","; + CW.writeOperand(I->getOperand(op), false, Out); + } + + Out << " );\n"; +} + +void CInstPrintVisitor::visitShr(ShiftInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "("; + CW.writeOperand(Operand, false, Out); + Out << " >> "; + Out << "("; + CW.writeOperand(I->getOperand(1), false, Out); + Out << "));\n"; +} + +void CInstPrintVisitor::visitShl(ShiftInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "("; + CW.writeOperand(Operand, false, Out); + Out << " << "; + Out << "("; + CW.writeOperand(I->getOperand(1), false, Out); + Out << "));\n"; +} + +// Specific Instruction type classes... note that all of the casts are +// neccesary because we use the instruction classes as opaque types... +// +void CInstPrintVisitor::visitReturnInst(ReturnInst *I) { + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "return "; + if (Operand) + CW.writeOperand(Operand,false, Out); + Out << ";\n"; +} + +void CInstPrintVisitor::visitBranchInst(BranchInst *I) { + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + TerminatorInst *tI = cast(I); + if (I->getNumOperands() > 1) { + Out << "if ("; + CW.writeOperand(I->getOperand(2),false, Out); + Out << ") {\n"; + printPhiFromNextBlock(tI,0); + Out << " goto "; + CW.writeOperand(Operand,false, Out); + Out << ";\n"; + Out << "}" << "else {\n"; + printPhiFromNextBlock(tI,1); + Out << " goto "; + CW.writeOperand(I->getOperand(1),false, Out); + Out << ";\n"; + Out << "}\n"; + } else { + printPhiFromNextBlock(tI,0); + Out << " goto "; + CW.writeOperand(Operand, false, Out); + Out << ";\n"; + } + Out << "\n"; +} + +void CInstPrintVisitor::visitSwitchInst(SwitchInst *I) { + Out << "\n"; +} + +void CInstPrintVisitor::visitInvokeInst(InvokeInst *I) { + Out << "\n"; +} + +void CInstPrintVisitor::visitMallocInst(MallocInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + string tempstr = ""; + Out << "("; + CW.printType(cast(I->getType())->getElementType(), Out); + Out << "*) malloc(sizeof("; + CW.printTypeVar(cast(I->getType())->getElementType(), + tempstr, Out); + Out << ")"; + if (I->getNumOperands()) { + Out << " * " ; + CW.writeOperand(Operand, false, Out); + } + Out << ");"; +} + +void CInstPrintVisitor::visitAllocaInst(AllocaInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + string tempstr = ""; + Out << "("; + CW.printTypeVar(I->getType(), tempstr, Out); + Out << ") alloca(sizeof("; + CW.printTypeVar(cast(I->getType())->getElementType(), + tempstr, Out); + Out << ")"; + if (I->getNumOperands()) { + Out << " * " ; + CW.writeOperand(Operand, false, Out); + } + Out << ");\n"; +} + +void CInstPrintVisitor::visitFreeInst(FreeInst *I) { + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "free("; + CW.writeOperand(Operand, false, Out); + Out << ");\n"; +} + +void CInstPrintVisitor::visitLoadInst(LoadInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + if (I->getNumOperands() <= 1) { + Out << "*"; + CW.writeOperand(Operand,false, Out); + } + else { + //Check if it is an array type or struct type ptr! + int arrtype = 1; + const PointerType *PTy = dyn_cast(I->getType()); + if (cast(Operand->getType())->getElementType()->getPrimitiveID() == Type::StructTyID) + arrtype = 0; + if (arrtype && isa(Operand)) + Out << "(&"; + CW.writeOperand(Operand,false, Out); + for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) { + if (i == 1) { + if (arrtype || !isa(Operand)) { + Out << "["; + CW.writeOperand(I->getOperand(i), false, Out); + Out << "]"; + } + if (isa(Operand) && arrtype) + Out << ")"; + } + else { + if (arrtype == 1) Out << "["; + else + Out << ".field"; + CW.writeOperand(I->getOperand(i), false, Out); + if (arrtype == 1) Out << "]"; + } + } + } + Out << ";\n"; +} + +void CInstPrintVisitor::visitStoreInst(StoreInst *I) { + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + if (I->getNumOperands() <= 2) { + Out << "*"; + CW.writeOperand(I->getOperand(1), false, Out); + } + else { + //Check if it is an array type or struct type ptr! + int arrtype = 1; + if (cast(I->getOperand(1)->getType())->getElementType()->getPrimitiveID() == Type::StructTyID) + arrtype = 0; + if (isa(I->getOperand(1)) && arrtype) + Out << "(&"; + CW.writeOperand(I->getOperand(1), false, Out); + for (unsigned i = 2, E = I->getNumOperands(); i != E; ++i) { + if (i == 2) { + if (arrtype || !isa(I->getOperand(1))) { + Out << "["; + CW.writeOperand(I->getOperand(i), false, Out); + Out << "]"; + } + if (isa(I->getOperand(1)) && arrtype) + Out << ")"; + } + else { + if (arrtype == 1) Out << "["; + else + Out << ".field"; + CW.writeOperand(I->getOperand(i), false, Out); + if (arrtype == 1) Out << "]"; + } + } + } + Out << " = "; + CW.writeOperand(Operand,false, Out); + Out << ";\n"; +} + +void CInstPrintVisitor::visitGetElementPtrInst(GetElementPtrInst *I) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << " &("; + if (I->getNumOperands() <= 1) + CW.writeOperand(Operand,false, Out); + else { + //Check if it is an array type or struct type ptr! + int arrtype = 1; + if ((cast(Operand->getType()))->getElementType()->getPrimitiveID() == Type::StructTyID) + arrtype = 0; + if ((isa(Operand)) && arrtype) + Out << "(&"; + CW.writeOperand(Operand,false, Out); + for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) { + if (i == 1) { + if (arrtype || !isa(Operand)){ + Out << "["; + CW.writeOperand(I->getOperand(i), false, Out); + Out << "]"; + } + if (isa(Operand) && arrtype) + Out << ")"; + } + else { + if (arrtype == 1) Out << "["; + else + Out << ".field"; + CW.writeOperand(I->getOperand(i), false, Out); + if (arrtype == 1) Out << "]"; + } + } + } + Out << ");\n"; +} + +void CInstPrintVisitor::visitPHINode(PHINode *I) { + +} + +void CInstPrintVisitor::visitUnaryOperator (UnaryOperator *I) { + if (I->getOpcode() == Instruction::Not) { + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + Out << "!("; + CW.writeOperand(Operand,false, Out); + Out << ");\n"; + } + else { + Out << "\n"; + } +} + +void CInstPrintVisitor::visitBinaryOperator(BinaryOperator *I) { + //binary instructions, shift instructions, setCond instructions. + outputLValue(I); + Operand = I->getNumOperands() ? I->getOperand(0) : 0; + if (I->getType()->getPrimitiveID() == Type::PointerTyID) { + Out << "("; + CW.printType(I->getType(), Out); + Out << ")"; + } + Out << "("; + if (Operand->getType()->getPrimitiveID() == Type::PointerTyID) + Out << "(long long)"; + CW.writeOperand(Operand,false, Out); + Out << getOpcodeOperName(I); + // Need the extra parenthisis if the second operand is < 0 + Out << '('; + if (I->getOperand(1)->getType()->getPrimitiveID() == Type::PointerTyID) + Out << "(long long)"; + CW.writeOperand(I->getOperand(1),false, Out); + Out << ')'; + Out << ");\n"; +} + +/* END : CInstPrintVisitor implementation */ + +void CWriter::printModule(const Module *M) { + // printing stdlib inclusion + // Out << "#include \n"; + + // Loop over the symbol table, emitting all named constants... + if (M->hasSymbolTable()) + printSymbolTable(*M->getSymbolTable()); + + for_each(M->gbegin(), M->gend(), + bind_obj(this, &CWriter::printGlobal)); + + // First output all the declarations of the methods as C requires Functions + // be declared before they are used. + for_each(M->begin(), M->end(), bind_obj(this,&CWriter::printFunctionDecl)); + + // declaration of alloca + Out << "void *alloca(unsigned long size);\n"; + + // Output all of the methods... + for_each(M->begin(), M->end(), bind_obj(this,&CWriter::printFunction)); +} + +// prints the global constants +void CWriter::printGlobal(const GlobalVariable *GV) { + string tempostr; + if (GV->hasName()) + tempostr = "llvm__" + makeNameProper(GV->getName()) + "_" + + itostr((int)GV->getType()->getUniqueID()); + if (GV->hasInternalLinkage()) Out << "static "; + + printTypeVar(GV->getType()->getElementType(), tempostr, Out); + + if (GV->hasInitializer()) { + Out << " = " ; + writeOperand(GV->getInitializer(), false, Out, false); + } + + Out << ";\n"; +} + +// printSymbolTable - Run through symbol table looking for named constants +// if a named constant is found, emit it's declaration... +// Assuming that symbol table has only types and constants. +void CWriter::printSymbolTable(const SymbolTable &ST) { + // GraphT G; + for (SymbolTable::const_iterator TI = ST.begin(); TI != ST.end(); ++TI) { + SymbolTable::type_const_iterator I = ST.type_begin(TI->first); + SymbolTable::type_const_iterator End = ST.type_end(TI->first); + + // TODO + // Need to run through all the used types in the program + // FindUsedTypes &FUT = new FindUsedTypes(); + // const std::set &UsedTypes = FUT.getTypes(); + // Filter out the structures printing forward definitions for each of them + // and creating the dependency graph. + // Print forward definitions to all of them + // print the typedefs topologically sorted + + // But for now we have + for (; I != End; ++I) { + const Value *V = I->second; + if (const Constant *CPV = dyn_cast(V)) { + printConstant(CPV); + } else if (const Type *Ty = dyn_cast(V)) { + string tempostr; + string tempstr = ""; + Out << "typedef "; + vector TypeStack; + tempostr = "llvm__" + I->first; + string TypeNameVar = calcTypeNameVar(Ty, TypeStack, TypeNames, + tempostr, tempstr); + Out << TypeNameVar << ";\n"; + if (!isa(Ty) || + !cast(Ty)->getElementType()->isPrimitiveType()) + TypeNames.insert(std::make_pair(Ty, "llvm__"+I->first)); + } + } + } +} + + +// printConstant - Print out a constant pool entry... +// +void CWriter::printConstant(const Constant *CPV) { + // TODO + // Dinakar : Don't know what to do with unnamed constants + // should do something about it later. + + string tempostr; + if (CPV->hasName()) { + // Print out name... + tempostr = "llvm__" + makeNameProper(CPV->getName()) + "_" + + itostr((int)CPV->getType()->getUniqueID()); + } else { + int Slot = Table.getValSlot(CPV); // slot number + if (Slot >= 0) + tempostr = "llvm__tmp_" + itostr(Slot) + "_" + + itostr((int)CPV->getType()->getUniqueID()); + else + tempostr = ""; + } + + // Print out the constant type... + printTypeVar(CPV->getType(), tempostr, Out); + + Out << " = "; + // Write the value out now... + writeOperand(CPV, false, Out, false); + + Out << "\n"; +} + + + +// printFunctionDecl - Print method declaration +// +void CWriter::printFunctionDecl(const Function *M) { + + if (M->hasInternalLinkage()) Out <<"static "; + + // Loop over the arguments, printing them... + const FunctionType *MT = cast(M->getFunctionType()); + + if (!M->isExternal()) { + // Print out the return type and name... + printType(M->getReturnType(), Out); + Out << " " << makeNameProper(M->getName()) << "("; + + for_each(M->getArgumentList().begin(), M->getArgumentList().end(), + bind_obj(this, &CWriter::printFunctionArgument)); + } else { + // Print out the return type and name... + printType(M->getReturnType(), Out) ; + Out << " " << makeNameProper(M->getName()) << "("; + + // Loop over the arguments, printing them... + const FunctionType *MT = cast(M->getFunctionType()); + for (FunctionType::ParamTypes::const_iterator I = + MT->getParamTypes().begin(), + E = MT->getParamTypes().end(); I != E; ++I) { + if (I != MT->getParamTypes().begin()) Out << ", "; + printType(*I, Out); + } + } + + // Finish printing arguments... + if (MT->isVarArg()) { + if (MT->getParamTypes().size()) Out << ", "; + Out << "..."; // Output varargs portion of signature! + } + Out << ");\n"; +} + +void CWriter::printFunction(const Function *M) { + if (!M->isExternal()) { + // Process each of the basic blocks, gather information and call the + // output methods on the CLocalVars and Function* objects. + + // gather local variable information for each basic block + InstLocalVarsVisitor ILV(Table); + ILV.visit((Function *)M); + + // Spout out code. + outputFunction(M, ILV.CLV); + + } +} + +// printFunctionArgument - This member is called for every argument that +// is passed into the method. Simply print it out +// +void CWriter::printFunctionArgument(const Argument *Arg) { + // Insert commas as we go... the first arg doesn't get a comma + string tempostr; + if (Arg != Arg->getParent()->getArgumentList().front()) Out << ", "; + + // Output name, if available... + if (Arg->hasName()) { + tempostr = "llvm__" + makeNameProper(Arg->getName()) + "_" + + itostr((int)Arg->getType()->getUniqueID()); + } else if (Table.getValSlot(Arg) < 0) { + tempostr = ""; + } + else { + tempostr = "llvm__tmp_" + itostr(Table.getValSlot(Arg)) + "_" + + itostr((int)Arg->getType()->getUniqueID()); + } + // Output type... + // printType(Arg->getType(), Out); + // Out << " " << tempostr; + printTypeVar (Arg->getType(), tempostr, Out); +} + +void CWriter::outputFunction(const Function *M, CLocalVars& CLV) { + // Currently we have a no-loop-structure implementation + // Seems like its not really necessary. + + // Print out the return type and name... + printType(M->getReturnType(), Out) ; + Out << " " << makeNameProper(M->getName()) << "("; + // Loop over the arguments, printing them... + const FunctionType *MT = cast(M->getFunctionType()); + + if (!M->isExternal()) { + for_each(M->getArgumentList().begin(), M->getArgumentList().end(), + bind_obj(this, &CWriter::printFunctionArgument)); + } else { + // Loop over the arguments, printing them... + const FunctionType *MT = cast(M->getFunctionType()); + for (FunctionType::ParamTypes::const_iterator I = + MT->getParamTypes().begin(), + E = MT->getParamTypes().end(); I != E; ++I) { + if (I != MT->getParamTypes().begin()) Out << ", "; + printType(*I, Out); + } + } + + // Finish printing arguments... + if (MT->isVarArg()) { + if (MT->getParamTypes().size()) Out << ", "; + Out << "..."; // Output varargs portion of signature! + } + Out << ")\n"; + + if (!M->isExternal()) { + Out << "{\n"; + // Loop over the symbol table, emitting all named constants... + if (M->hasSymbolTable()) + printSymbolTable(*M->getSymbolTable()); + + // print the local variables + // we assume that every local variable is alloca'ed in the C code. + std::map locals; + locals = CLV.LocalVars; + + map::iterator iter; + for (iter = locals.begin(); iter != locals.end(); iter++) { + VarListType::iterator listiter; + for (listiter = iter->second.begin(); listiter != iter->second.end(); + listiter++) { + // printType(iter->first, Out); + // Out << " " << *listiter << ";\n"; + printTypeVar(iter->first, *listiter, Out); + Out << ";\n"; + } + } + + // print the basic blocks + Function::const_iterator iterBB; + for (iterBB = M->begin(); iterBB != M->end(); ++iterBB) + outputBasicBlock(*iterBB); + + Out << "}\n"; + } +} + +void CWriter::outputBasicBlock(const BasicBlock* BB) { + + if (BB->hasName()) { // Print out the label if it exists... + Out << "llvm__" << makeNameProper(BB->getName()) << "_" + << BB->getType()->getUniqueID() << ":\n"; + } else { + int Slot = Table.getValSlot(BB); + Out << "llvm__tmp_"; + if (Slot >= 0) + Out << Slot << "_" << BB->getType()->getUniqueID() << ":\n"; + // Extra newline seperates out label's + else + Out << "\n"; + } + + // Output all of the instructions in the basic block... + // print the basic blocks + CInstPrintVisitor CIPV(*this, Table, Out); + CIPV.visit((BasicBlock *) BB); +} + +// printTypeVar - Go to extreme measures to attempt to print out a short, +// symbolic version of a type name. +// +ostream& CWriter::printTypeVar(const Type *Ty, string VariableName, + ostream &Out) { + return printTypeVarInt(Out, Ty, TypeNames, VariableName); +} + +// printType - Go to extreme measures to attempt to print out a short, symbolic +// version of a type name. +ostream& CWriter::printType(const Type *Ty, ostream &Out) { + return printTypeInt(Out, Ty, TypeNames); +} + + +void CWriter::writeOperand(const Value *Operand, bool PrintType, + ostream &Out, bool PrintName = true) { + if (PrintType){ + string tempstr = ""; + Out << " "; + printType(Operand->getType(), Out); + } + vector TypeStack; + string MInfo = ""; + string OperandType = calcTypeName(Operand->getType(), TypeStack, TypeNames, + &MInfo); + if (MInfo != "") + OperandType += ")" + MInfo; + WriteCOperandInternal(Out, Operand, PrintName, &Table, OperandType); +} + + +//===----------------------------------------------------------------------===// +// External Interface declaration +//===----------------------------------------------------------------------===// + + +void WriteToC(const Module *C, ostream &Out) { + assert(C && "You can't write a null module!!"); + SlotCalculator SlotTable(C, true); + CWriter W(Out, SlotTable, C); + W.write(C); + Out.flush(); +} + diff --git a/tools/dis/Makefile b/tools/dis/Makefile index b9a314b7e3..0bd888e955 100644 --- a/tools/dis/Makefile +++ b/tools/dis/Makefile @@ -1,7 +1,7 @@ LEVEL = ../.. TOOLNAME = dis -USEDLIBS = bcreader vmcore support +USEDLIBS = bcreader vmcore support cwriter include $(LEVEL)/Makefile.common diff --git a/tools/dis/dis.cpp b/tools/dis/dis.cpp index e3d0ef0a4b..1351f878b3 100644 --- a/tools/dis/dis.cpp +++ b/tools/dis/dis.cpp @@ -11,6 +11,8 @@ // -rdfo - Print basic blocks in reverse depth first order // -po - Print basic blocks in post order // -rpo - Print basic blocks in reverse post order +// +// -c - Print C code // // TODO: add -vcg which prints VCG compatible output. // @@ -23,6 +25,7 @@ #include "Support/PostOrderIterator.h" #include "Support/CommandLine.h" #include "Support/Signals.h" +#include "llvm/Assembly/CWriter.h" #include #include using std::cerr; @@ -34,6 +37,8 @@ enum OutputMode { rdfo, // Reverse Depth First ordering po, // Post Order rpo, // Reverse Post Order + + c, // Generate C code }; cl::String InputFilename ("", "Load file, print as assembly", 0, "-"); @@ -45,6 +50,8 @@ cl::EnumFlags WriteMode(cl::NoFlags, clEnumVal(rdfo , "Write basic blocks in reverse DFO"), clEnumVal(po , "Write basic blocks in postorder"), clEnumVal(rpo , "Write basic blocks in reverse postorder"), + + clEnumVal(c , "Write corresponding C code"), 0); int main(int argc, char **argv) { @@ -77,7 +84,10 @@ int main(int argc, char **argv) { } else { OutputFilename = IFN; // Append a .ll to it } - OutputFilename += ".ll"; + if (WriteMode == c) + OutputFilename += ".c"; + else + OutputFilename += ".ll"; if (!Force && std::ifstream(OutputFilename.c_str())) { // If force is not specified, make sure not to overwrite a file! @@ -99,11 +109,12 @@ int main(int argc, char **argv) { Out = &std::cout; } - // All that dis does is write the assembly out to a file... which is exactly - // what the writer library is supposed to do... - // + // All that dis does is write the assembly or C out to a file... which is + // exactly what the writer or cwriter library is supposed to do... if (WriteMode == Default) { (*Out) << M; // Print out in list order + } else if (WriteMode == c) { + WriteToC(M, *Out); } else { // TODO: This does not print anything other than the basic blocks in the // functions... more should definately be printed. It should be valid @@ -145,3 +156,4 @@ int main(int argc, char **argv) { if (Out != &std::cout) delete Out; return 0; } + diff --git a/tools/llvm-dis/Makefile b/tools/llvm-dis/Makefile index b9a314b7e3..0bd888e955 100644 --- a/tools/llvm-dis/Makefile +++ b/tools/llvm-dis/Makefile @@ -1,7 +1,7 @@ LEVEL = ../.. TOOLNAME = dis -USEDLIBS = bcreader vmcore support +USEDLIBS = bcreader vmcore support cwriter include $(LEVEL)/Makefile.common diff --git a/tools/llvm-dis/dis.cpp b/tools/llvm-dis/dis.cpp index e3d0ef0a4b..1351f878b3 100644 --- a/tools/llvm-dis/dis.cpp +++ b/tools/llvm-dis/dis.cpp @@ -11,6 +11,8 @@ // -rdfo - Print basic blocks in reverse depth first order // -po - Print basic blocks in post order // -rpo - Print basic blocks in reverse post order +// +// -c - Print C code // // TODO: add -vcg which prints VCG compatible output. // @@ -23,6 +25,7 @@ #include "Support/PostOrderIterator.h" #include "Support/CommandLine.h" #include "Support/Signals.h" +#include "llvm/Assembly/CWriter.h" #include #include using std::cerr; @@ -34,6 +37,8 @@ enum OutputMode { rdfo, // Reverse Depth First ordering po, // Post Order rpo, // Reverse Post Order + + c, // Generate C code }; cl::String InputFilename ("", "Load file, print as assembly", 0, "-"); @@ -45,6 +50,8 @@ cl::EnumFlags WriteMode(cl::NoFlags, clEnumVal(rdfo , "Write basic blocks in reverse DFO"), clEnumVal(po , "Write basic blocks in postorder"), clEnumVal(rpo , "Write basic blocks in reverse postorder"), + + clEnumVal(c , "Write corresponding C code"), 0); int main(int argc, char **argv) { @@ -77,7 +84,10 @@ int main(int argc, char **argv) { } else { OutputFilename = IFN; // Append a .ll to it } - OutputFilename += ".ll"; + if (WriteMode == c) + OutputFilename += ".c"; + else + OutputFilename += ".ll"; if (!Force && std::ifstream(OutputFilename.c_str())) { // If force is not specified, make sure not to overwrite a file! @@ -99,11 +109,12 @@ int main(int argc, char **argv) { Out = &std::cout; } - // All that dis does is write the assembly out to a file... which is exactly - // what the writer library is supposed to do... - // + // All that dis does is write the assembly or C out to a file... which is + // exactly what the writer or cwriter library is supposed to do... if (WriteMode == Default) { (*Out) << M; // Print out in list order + } else if (WriteMode == c) { + WriteToC(M, *Out); } else { // TODO: This does not print anything other than the basic blocks in the // functions... more should definately be printed. It should be valid @@ -145,3 +156,4 @@ int main(int argc, char **argv) { if (Out != &std::cout) delete Out; return 0; } + diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index e3d0ef0a4b..1351f878b3 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -11,6 +11,8 @@ // -rdfo - Print basic blocks in reverse depth first order // -po - Print basic blocks in post order // -rpo - Print basic blocks in reverse post order +// +// -c - Print C code // // TODO: add -vcg which prints VCG compatible output. // @@ -23,6 +25,7 @@ #include "Support/PostOrderIterator.h" #include "Support/CommandLine.h" #include "Support/Signals.h" +#include "llvm/Assembly/CWriter.h" #include #include using std::cerr; @@ -34,6 +37,8 @@ enum OutputMode { rdfo, // Reverse Depth First ordering po, // Post Order rpo, // Reverse Post Order + + c, // Generate C code }; cl::String InputFilename ("", "Load file, print as assembly", 0, "-"); @@ -45,6 +50,8 @@ cl::EnumFlags WriteMode(cl::NoFlags, clEnumVal(rdfo , "Write basic blocks in reverse DFO"), clEnumVal(po , "Write basic blocks in postorder"), clEnumVal(rpo , "Write basic blocks in reverse postorder"), + + clEnumVal(c , "Write corresponding C code"), 0); int main(int argc, char **argv) { @@ -77,7 +84,10 @@ int main(int argc, char **argv) { } else { OutputFilename = IFN; // Append a .ll to it } - OutputFilename += ".ll"; + if (WriteMode == c) + OutputFilename += ".c"; + else + OutputFilename += ".ll"; if (!Force && std::ifstream(OutputFilename.c_str())) { // If force is not specified, make sure not to overwrite a file! @@ -99,11 +109,12 @@ int main(int argc, char **argv) { Out = &std::cout; } - // All that dis does is write the assembly out to a file... which is exactly - // what the writer library is supposed to do... - // + // All that dis does is write the assembly or C out to a file... which is + // exactly what the writer or cwriter library is supposed to do... if (WriteMode == Default) { (*Out) << M; // Print out in list order + } else if (WriteMode == c) { + WriteToC(M, *Out); } else { // TODO: This does not print anything other than the basic blocks in the // functions... more should definately be printed. It should be valid @@ -145,3 +156,4 @@ int main(int argc, char **argv) { if (Out != &std::cout) delete Out; return 0; } + -- cgit v1.2.3