| Chris Lattner | 3af3ba8 | 2002-05-09 21:31:18 +0000 | [diff] [blame] | 1 | //===-- Writer.cpp - Library for converting LLVM code to C ----------------===// | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | // This library implements the functionality defined in llvm/Assembly/CWriter.h | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 4 | // | 
|  | 5 | // TODO : Recursive types. | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 6 | // | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 7 | //===-----------------------------------------------------------------------==// | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 8 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 9 | #include "llvm/Assembly/CWriter.h" | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 10 | #include "llvm/Constants.h" | 
| Chris Lattner | 2f5f51a | 2002-05-09 03:28:37 +0000 | [diff] [blame] | 11 | #include "llvm/DerivedTypes.h" | 
|  | 12 | #include "llvm/Module.h" | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 13 | #include "llvm/iMemory.h" | 
|  | 14 | #include "llvm/iTerminators.h" | 
|  | 15 | #include "llvm/iPHINode.h" | 
|  | 16 | #include "llvm/iOther.h" | 
| Chris Lattner | 2f5f51a | 2002-05-09 03:28:37 +0000 | [diff] [blame] | 17 | #include "llvm/iOperators.h" | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 18 | #include "llvm/SymbolTable.h" | 
| Chris Lattner | 3af3ba8 | 2002-05-09 21:31:18 +0000 | [diff] [blame] | 19 | #include "llvm/SlotCalculator.h" | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 20 | #include "llvm/Support/InstVisitor.h" | 
| Chris Lattner | 7683a12 | 2002-05-09 20:33:35 +0000 | [diff] [blame] | 21 | #include "llvm/Support/InstIterator.h" | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 22 | #include "Support/StringExtras.h" | 
|  | 23 | #include "Support/STLExtras.h" | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 24 | #include <algorithm> | 
| Chris Lattner | 78771c8 | 2002-05-17 04:55:35 +0000 | [diff] [blame] | 25 | #include <set> | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 26 | using std::string; | 
|  | 27 | using std::map; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 28 | using std::ostream; | 
|  | 29 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 30 | static std::string getConstStrValue(const Constant* CPV); | 
|  | 31 |  | 
|  | 32 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 33 | static std::string getConstArrayStrValue(const Constant* CPV) { | 
|  | 34 | std::string Result; | 
|  | 35 |  | 
|  | 36 | // As a special case, print the array as a string if it is an array of | 
|  | 37 | // ubytes or an array of sbytes with positive values. | 
|  | 38 | // | 
|  | 39 | const Type *ETy = cast<ArrayType>(CPV->getType())->getElementType(); | 
|  | 40 | bool isString = (ETy == Type::SByteTy || ETy == Type::UByteTy); | 
|  | 41 |  | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 42 | // Make sure the last character is a null char, as automatically added by C | 
|  | 43 | if (CPV->getNumOperands() == 0 || | 
|  | 44 | !cast<Constant>(*(CPV->op_end()-1))->isNullValue()) | 
|  | 45 | isString = false; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 46 |  | 
|  | 47 | if (isString) { | 
|  | 48 | Result = "\""; | 
| Chris Lattner | 2f5eb4e | 2002-05-09 03:56:52 +0000 | [diff] [blame] | 49 | // Do not include the last character, which we know is null | 
|  | 50 | for (unsigned i = 0, e = CPV->getNumOperands()-1; i != e; ++i) { | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 51 | unsigned char C = (ETy == Type::SByteTy) ? | 
|  | 52 | (unsigned char)cast<ConstantSInt>(CPV->getOperand(i))->getValue() : | 
|  | 53 | (unsigned char)cast<ConstantUInt>(CPV->getOperand(i))->getValue(); | 
|  | 54 |  | 
|  | 55 | if (isprint(C)) { | 
|  | 56 | Result += C; | 
|  | 57 | } else { | 
| Chris Lattner | 2f5eb4e | 2002-05-09 03:56:52 +0000 | [diff] [blame] | 58 | switch (C) { | 
|  | 59 | case '\n': Result += "\\n"; break; | 
|  | 60 | case '\t': Result += "\\t"; break; | 
|  | 61 | case '\r': Result += "\\r"; break; | 
|  | 62 | case '\v': Result += "\\v"; break; | 
|  | 63 | case '\a': Result += "\\a"; break; | 
|  | 64 | default: | 
|  | 65 | Result += "\\x"; | 
|  | 66 | Result += ( C/16  < 10) ? ( C/16 +'0') : ( C/16 -10+'A'); | 
|  | 67 | Result += ((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'); | 
|  | 68 | break; | 
|  | 69 | } | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 70 | } | 
|  | 71 | } | 
|  | 72 | Result += "\""; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 73 | } else { | 
|  | 74 | Result = "{"; | 
|  | 75 | if (CPV->getNumOperands()) { | 
|  | 76 | Result += " " +  getConstStrValue(cast<Constant>(CPV->getOperand(0))); | 
|  | 77 | for (unsigned i = 1; i < CPV->getNumOperands(); i++) | 
|  | 78 | Result += ", " + getConstStrValue(cast<Constant>(CPV->getOperand(i))); | 
|  | 79 | } | 
|  | 80 | Result += " }"; | 
|  | 81 | } | 
|  | 82 |  | 
|  | 83 | return Result; | 
|  | 84 | } | 
|  | 85 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 86 | static std::string getConstStrValue(const Constant* CPV) { | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 87 | switch (CPV->getType()->getPrimitiveID()) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 88 | case Type::BoolTyID:  return CPV == ConstantBool::False ? "0" : "1"; | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 89 | case Type::SByteTyID: | 
|  | 90 | case Type::ShortTyID: | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 91 | case Type::IntTyID:   return itostr(cast<ConstantSInt>(CPV)->getValue()); | 
|  | 92 | case Type::LongTyID:  return itostr(cast<ConstantSInt>(CPV)->getValue())+"ll"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 93 |  | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 94 | case Type::UByteTyID: | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 95 | case Type::UShortTyID:return utostr(cast<ConstantUInt>(CPV)->getValue()); | 
|  | 96 | case Type::UIntTyID:  return utostr(cast<ConstantUInt>(CPV)->getValue())+"u"; | 
|  | 97 | case Type::ULongTyID:return utostr(cast<ConstantUInt>(CPV)->getValue())+"ull"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 98 |  | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 99 | case Type::FloatTyID: | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 100 | case Type::DoubleTyID: return ftostr(cast<ConstantFP>(CPV)->getValue()); | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 101 |  | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 102 | case Type::ArrayTyID:  return getConstArrayStrValue(CPV); | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 103 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 104 | case Type::StructTyID: { | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 105 | std::string Result = "{"; | 
|  | 106 | if (CPV->getNumOperands()) { | 
|  | 107 | Result += " " + getConstStrValue(cast<Constant>(CPV->getOperand(0))); | 
|  | 108 | for (unsigned i = 1; i < CPV->getNumOperands(); i++) | 
|  | 109 | Result += ", " + getConstStrValue(cast<Constant>(CPV->getOperand(i))); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 110 | } | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 111 | return Result + " }"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 112 | } | 
|  | 113 |  | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 114 | default: | 
|  | 115 | cerr << "Unknown constant type: " << CPV << "\n"; | 
|  | 116 | abort(); | 
|  | 117 | } | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 118 | } | 
|  | 119 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 120 | // Pass the Type* variable and and the variable name and this prints out the | 
|  | 121 | // variable declaration. | 
| Chris Lattner | deed7a5 | 2002-05-09 15:18:52 +0000 | [diff] [blame] | 122 | // | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 123 | static string calcTypeNameVar(const Type *Ty, | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 124 | map<const Type *, string> &TypeNames, | 
|  | 125 | const string &NameSoFar, bool ignoreName = false){ | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 126 | if (Ty->isPrimitiveType()) | 
|  | 127 | switch (Ty->getPrimitiveID()) { | 
| Chris Lattner | deed7a5 | 2002-05-09 15:18:52 +0000 | [diff] [blame] | 128 | case Type::VoidTyID:   return "void " + NameSoFar; | 
|  | 129 | case Type::BoolTyID:   return "bool " + NameSoFar; | 
|  | 130 | case Type::UByteTyID:  return "unsigned char " + NameSoFar; | 
|  | 131 | case Type::SByteTyID:  return "signed char " + NameSoFar; | 
|  | 132 | case Type::UShortTyID: return "unsigned short " + NameSoFar; | 
|  | 133 | case Type::ShortTyID:  return "short " + NameSoFar; | 
|  | 134 | case Type::UIntTyID:   return "unsigned " + NameSoFar; | 
|  | 135 | case Type::IntTyID:    return "int " + NameSoFar; | 
|  | 136 | case Type::ULongTyID:  return "unsigned long long " + NameSoFar; | 
|  | 137 | case Type::LongTyID:   return "signed long long " + NameSoFar; | 
| Chris Lattner | 1f02c89 | 2002-05-09 20:14:10 +0000 | [diff] [blame] | 138 | case Type::FloatTyID:  return "float " + NameSoFar; | 
|  | 139 | case Type::DoubleTyID: return "double " + NameSoFar; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 140 | default : | 
| Chris Lattner | deed7a5 | 2002-05-09 15:18:52 +0000 | [diff] [blame] | 141 | cerr << "Unknown primitive type: " << Ty << "\n"; | 
|  | 142 | abort(); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 143 | } | 
|  | 144 |  | 
|  | 145 | // Check to see if the type is named. | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 146 | if (!ignoreName) { | 
|  | 147 | map<const Type *, string>::iterator I = TypeNames.find(Ty); | 
|  | 148 | if (I != TypeNames.end()) | 
|  | 149 | return I->second + " " + NameSoFar; | 
|  | 150 | } | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 151 |  | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 152 | string Result; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 153 | switch (Ty->getPrimitiveID()) { | 
|  | 154 | case Type::FunctionTyID: { | 
| Chris Lattner | 7683a12 | 2002-05-09 20:33:35 +0000 | [diff] [blame] | 155 | const FunctionType *MTy = cast<FunctionType>(Ty); | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 156 | Result += calcTypeNameVar(MTy->getReturnType(), TypeNames, ""); | 
| Chris Lattner | 7683a12 | 2002-05-09 20:33:35 +0000 | [diff] [blame] | 157 | Result += " " + NameSoFar + " ("; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 158 | for (FunctionType::ParamTypes::const_iterator | 
|  | 159 | I = MTy->getParamTypes().begin(), | 
|  | 160 | E = MTy->getParamTypes().end(); I != E; ++I) { | 
|  | 161 | if (I != MTy->getParamTypes().begin()) | 
|  | 162 | Result += ", "; | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 163 | Result += calcTypeNameVar(*I, TypeNames, ""); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 164 | } | 
|  | 165 | if (MTy->isVarArg()) { | 
|  | 166 | if (!MTy->getParamTypes().empty()) | 
|  | 167 | Result += ", "; | 
|  | 168 | Result += "..."; | 
|  | 169 | } | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 170 | return Result + ")"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 171 | } | 
|  | 172 | case Type::StructTyID: { | 
|  | 173 | const StructType *STy = cast<const StructType>(Ty); | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 174 | Result = NameSoFar + " {\n"; | 
|  | 175 | unsigned indx = 0; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 176 | for (StructType::ElementTypes::const_iterator | 
|  | 177 | I = STy->getElementTypes().begin(), | 
|  | 178 | E = STy->getElementTypes().end(); I != E; ++I) { | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 179 | Result += "  " +calcTypeNameVar(*I, TypeNames, "field" + utostr(indx++)); | 
|  | 180 | Result += ";\n"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 181 | } | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 182 | return Result + "}"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 183 | } | 
|  | 184 |  | 
| Chris Lattner | 3af3ba8 | 2002-05-09 21:31:18 +0000 | [diff] [blame] | 185 | case Type::PointerTyID: | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 186 | return calcTypeNameVar(cast<const PointerType>(Ty)->getElementType(), | 
|  | 187 | TypeNames, "*" + NameSoFar); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 188 |  | 
|  | 189 | case Type::ArrayTyID: { | 
|  | 190 | const ArrayType *ATy = cast<const ArrayType>(Ty); | 
|  | 191 | int NumElements = ATy->getNumElements(); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 192 | return calcTypeNameVar(ATy->getElementType(), TypeNames, | 
|  | 193 | NameSoFar + "[" + itostr(NumElements) + "]"); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 194 | } | 
|  | 195 | default: | 
|  | 196 | assert(0 && "Unhandled case in getTypeProps!"); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 197 | abort(); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 198 | } | 
|  | 199 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 200 | return Result; | 
|  | 201 | } | 
|  | 202 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 203 | namespace { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 204 | class CWriter : public InstVisitor<CWriter> { | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 205 | ostream& Out; | 
|  | 206 | SlotCalculator &Table; | 
|  | 207 | const Module *TheModule; | 
|  | 208 | map<const Type *, string> TypeNames; | 
| Chris Lattner | 78771c8 | 2002-05-17 04:55:35 +0000 | [diff] [blame] | 209 | std::set<const Value*> MangledGlobals; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 210 | public: | 
|  | 211 | inline CWriter(ostream &o, SlotCalculator &Tab, const Module *M) | 
|  | 212 | : Out(o), Table(Tab), TheModule(M) { | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 213 | } | 
|  | 214 |  | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 215 | inline void write(Module *M) { printModule(M); } | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 216 |  | 
| Chris Lattner | 3af3ba8 | 2002-05-09 21:31:18 +0000 | [diff] [blame] | 217 | ostream& printType(const Type *Ty, const string &VariableName = "") { | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 218 | return Out << calcTypeNameVar(Ty, TypeNames, VariableName); | 
| Chris Lattner | b5af06a | 2002-05-09 03:06:06 +0000 | [diff] [blame] | 219 | } | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 220 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 221 | void writeOperand(Value *Operand); | 
|  | 222 | void writeOperandInternal(Value *Operand); | 
| Chris Lattner | b5af06a | 2002-05-09 03:06:06 +0000 | [diff] [blame] | 223 |  | 
|  | 224 | string getValueName(const Value *V); | 
| Chris Lattner | b5af06a | 2002-05-09 03:06:06 +0000 | [diff] [blame] | 225 |  | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 226 | private : | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 227 | void printModule(Module *M); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 228 | void printSymbolTable(const SymbolTable &ST); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 229 | void printGlobal(const GlobalVariable *GV); | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 230 | void printFunctionSignature(const Function *F); | 
|  | 231 | void printFunctionDecl(const Function *F); // Print just the forward decl | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 232 |  | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 233 | void printFunction(Function *); | 
| Chris Lattner | b5af06a | 2002-05-09 03:06:06 +0000 | [diff] [blame] | 234 |  | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 235 | // isInlinableInst - Attempt to inline instructions into their uses to build | 
|  | 236 | // trees as much as possible.  To do this, we have to consistently decide | 
|  | 237 | // what is acceptable to inline, so that variable declarations don't get | 
|  | 238 | // printed and an extra copy of the expr is not emitted. | 
|  | 239 | // | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 240 | static bool isInlinableInst(const Instruction &I) { | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 241 | // Must be an expression, must be used exactly once.  If it is dead, we | 
|  | 242 | // emit it inline where it would go. | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 243 | if (I.getType() == Type::VoidTy || I.use_size() != 1 || | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 244 | isa<TerminatorInst>(I) || isa<CallInst>(I) || isa<PHINode>(I)) | 
|  | 245 | return false; | 
|  | 246 |  | 
|  | 247 | // Only inline instruction it it's use is in the same BB as the inst. | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 248 | return I.getParent() == cast<Instruction>(I.use_back())->getParent(); | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 249 | } | 
|  | 250 |  | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 251 | // Instruction visitation functions | 
|  | 252 | friend class InstVisitor<CWriter>; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 253 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 254 | void visitReturnInst(ReturnInst &I); | 
|  | 255 | void visitBranchInst(BranchInst &I); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 256 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 257 | void visitPHINode(PHINode &I) {} | 
|  | 258 | void visitNot(GenericUnaryInst &I); | 
|  | 259 | void visitBinaryOperator(Instruction &I); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 260 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 261 | void visitCastInst (CastInst &I); | 
|  | 262 | void visitCallInst (CallInst &I); | 
|  | 263 | void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); } | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 264 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 265 | void visitMallocInst(MallocInst &I); | 
|  | 266 | void visitAllocaInst(AllocaInst &I); | 
|  | 267 | void visitFreeInst  (FreeInst   &I); | 
|  | 268 | void visitLoadInst  (LoadInst   &I); | 
|  | 269 | void visitStoreInst (StoreInst  &I); | 
|  | 270 | void visitGetElementPtrInst(GetElementPtrInst &I); | 
| Chris Lattner | 2f5f51a | 2002-05-09 03:28:37 +0000 | [diff] [blame] | 271 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 272 | void visitInstruction(Instruction &I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 273 | cerr << "C Writer does not know about " << I; | 
|  | 274 | abort(); | 
|  | 275 | } | 
|  | 276 |  | 
|  | 277 | void outputLValue(Instruction *I) { | 
|  | 278 | Out << "  " << getValueName(I) << " = "; | 
|  | 279 | } | 
|  | 280 | void printBranchToBlock(BasicBlock *CurBlock, BasicBlock *SuccBlock, | 
|  | 281 | unsigned Indent); | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 282 | void printIndexingExpr(MemAccessInst &MAI); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 283 | }; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 284 | } | 
|  | 285 |  | 
| Chris Lattner | 2f49902 | 2002-05-09 04:21:21 +0000 | [diff] [blame] | 286 | // We dont want identifier names with ., space, -  in them. | 
|  | 287 | // So we replace them with _ | 
|  | 288 | static string makeNameProper(string x) { | 
|  | 289 | string tmp; | 
|  | 290 | for (string::iterator sI = x.begin(), sEnd = x.end(); sI != sEnd; sI++) | 
|  | 291 | switch (*sI) { | 
| Chris Lattner | deed7a5 | 2002-05-09 15:18:52 +0000 | [diff] [blame] | 292 | case '.': tmp += "d_"; break; | 
|  | 293 | case ' ': tmp += "s_"; break; | 
|  | 294 | case '-': tmp += "D_"; break; | 
| Chris Lattner | 2f49902 | 2002-05-09 04:21:21 +0000 | [diff] [blame] | 295 | default:  tmp += *sI; | 
|  | 296 | } | 
|  | 297 |  | 
|  | 298 | return tmp; | 
|  | 299 | } | 
|  | 300 |  | 
| Chris Lattner | b5af06a | 2002-05-09 03:06:06 +0000 | [diff] [blame] | 301 | string CWriter::getValueName(const Value *V) { | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 302 | if (V->hasName()) {              // Print out the label if it exists... | 
|  | 303 | if (isa<GlobalValue>(V) &&     // Do not mangle globals... | 
|  | 304 | cast<GlobalValue>(V)->hasExternalLinkage() && // Unless it's internal or | 
|  | 305 | !MangledGlobals.count(V))  // Unless the name would collide if we don't | 
| Chris Lattner | 2f49902 | 2002-05-09 04:21:21 +0000 | [diff] [blame] | 306 | return makeNameProper(V->getName()); | 
|  | 307 |  | 
| Chris Lattner | 2d05a1a | 2002-05-09 05:16:40 +0000 | [diff] [blame] | 308 | return "l" + utostr(V->getType()->getUniqueID()) + "_" + | 
|  | 309 | makeNameProper(V->getName()); | 
| Chris Lattner | 2f49902 | 2002-05-09 04:21:21 +0000 | [diff] [blame] | 310 | } | 
| Chris Lattner | b5af06a | 2002-05-09 03:06:06 +0000 | [diff] [blame] | 311 |  | 
|  | 312 | int Slot = Table.getValSlot(V); | 
|  | 313 | assert(Slot >= 0 && "Invalid value!"); | 
| Chris Lattner | 2d05a1a | 2002-05-09 05:16:40 +0000 | [diff] [blame] | 314 | return "ltmp_" + itostr(Slot) + "_" + utostr(V->getType()->getUniqueID()); | 
| Chris Lattner | b5af06a | 2002-05-09 03:06:06 +0000 | [diff] [blame] | 315 | } | 
|  | 316 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 317 | void CWriter::writeOperandInternal(Value *Operand) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 318 | if (Operand->hasName()) { | 
|  | 319 | Out << getValueName(Operand); | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 320 | } else if (Constant *CPV = dyn_cast<Constant>(Operand)) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 321 | if (isa<ConstantPointerNull>(CPV)) { | 
|  | 322 | Out << "(("; | 
| Chris Lattner | 3af3ba8 | 2002-05-09 21:31:18 +0000 | [diff] [blame] | 323 | printType(CPV->getType(), ""); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 324 | Out << ")NULL)"; | 
|  | 325 | } else | 
|  | 326 | Out << getConstStrValue(CPV); | 
|  | 327 | } else { | 
|  | 328 | int Slot = Table.getValSlot(Operand); | 
|  | 329 | assert(Slot >= 0 && "Malformed LLVM!"); | 
|  | 330 | Out << "ltmp_" << Slot << "_" << Operand->getType()->getUniqueID(); | 
|  | 331 | } | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 332 | } | 
|  | 333 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 334 | void CWriter::writeOperand(Value *Operand) { | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 335 | if (Instruction *I = dyn_cast<Instruction>(Operand)) | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 336 | if (isInlinableInst(*I)) { | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 337 | // Should we inline this instruction to build a tree? | 
|  | 338 | Out << "("; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 339 | visit(*I); | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 340 | Out << ")"; | 
|  | 341 | return; | 
|  | 342 | } | 
|  | 343 |  | 
|  | 344 | if (isa<GlobalVariable>(Operand)) | 
|  | 345 | Out << "(&";  // Global variables are references as their addresses by llvm | 
|  | 346 |  | 
|  | 347 | writeOperandInternal(Operand); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 348 |  | 
|  | 349 | if (isa<GlobalVariable>(Operand)) | 
|  | 350 | Out << ")"; | 
|  | 351 | } | 
|  | 352 |  | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 353 | void CWriter::printModule(Module *M) { | 
| Chris Lattner | 78771c8 | 2002-05-17 04:55:35 +0000 | [diff] [blame] | 354 | // Calculate which global values have names that will collide when we throw | 
|  | 355 | // away type information. | 
| Chris Lattner | 594b9fa | 2002-05-21 21:10:04 +0000 | [diff] [blame] | 356 | {  // Scope to delete the FoundNames set when we are done with it... | 
| Chris Lattner | 78771c8 | 2002-05-17 04:55:35 +0000 | [diff] [blame] | 357 | std::set<string> FoundNames; | 
|  | 358 | for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 359 | if (I->hasName())                      // If the global has a name... | 
|  | 360 | if (FoundNames.count(I->getName()))  // And the name is already used | 
|  | 361 | MangledGlobals.insert(I);          // Mangle the name | 
| Chris Lattner | 78771c8 | 2002-05-17 04:55:35 +0000 | [diff] [blame] | 362 | else | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 363 | FoundNames.insert(I->getName());   // Otherwise, keep track of name | 
| Chris Lattner | 78771c8 | 2002-05-17 04:55:35 +0000 | [diff] [blame] | 364 |  | 
|  | 365 | for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I) | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 366 | if (I->hasName())                      // If the global has a name... | 
|  | 367 | if (FoundNames.count(I->getName()))  // And the name is already used | 
|  | 368 | MangledGlobals.insert(I);          // Mangle the name | 
| Chris Lattner | 78771c8 | 2002-05-17 04:55:35 +0000 | [diff] [blame] | 369 | else | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 370 | FoundNames.insert(I->getName());   // Otherwise, keep track of name | 
| Chris Lattner | 78771c8 | 2002-05-17 04:55:35 +0000 | [diff] [blame] | 371 | } | 
|  | 372 |  | 
|  | 373 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 374 | // printing stdlib inclusion | 
|  | 375 | // Out << "#include <stdlib.h>\n"; | 
|  | 376 |  | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 377 | // get declaration for alloca | 
|  | 378 | Out << "/* Provide Declarations */\n" | 
| Chris Lattner | 594b9fa | 2002-05-21 21:10:04 +0000 | [diff] [blame] | 379 | << "#include <malloc.h>\n" | 
| Chris Lattner | b5af06a | 2002-05-09 03:06:06 +0000 | [diff] [blame] | 380 | << "#include <alloca.h>\n\n" | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 381 |  | 
|  | 382 | // Provide a definition for null if one does not already exist. | 
| Chris Lattner | b5af06a | 2002-05-09 03:06:06 +0000 | [diff] [blame] | 383 | << "#ifndef NULL\n#define NULL 0\n#endif\n\n" | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 384 | << "typedef unsigned char bool;\n" | 
|  | 385 |  | 
|  | 386 | << "\n\n/* Global Symbols */\n"; | 
|  | 387 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 388 | // Loop over the symbol table, emitting all named constants... | 
|  | 389 | if (M->hasSymbolTable()) | 
|  | 390 | printSymbolTable(*M->getSymbolTable()); | 
|  | 391 |  | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 392 | Out << "\n\n/* Global Data */\n"; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 393 | for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I) { | 
|  | 394 | if (I->hasInternalLinkage()) Out << "static "; | 
|  | 395 | printType(I->getType()->getElementType(), getValueName(I)); | 
| Chris Lattner | deed7a5 | 2002-05-09 15:18:52 +0000 | [diff] [blame] | 396 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 397 | if (I->hasInitializer()) { | 
| Chris Lattner | deed7a5 | 2002-05-09 15:18:52 +0000 | [diff] [blame] | 398 | Out << " = " ; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 399 | writeOperand(I->getInitializer()); | 
| Chris Lattner | deed7a5 | 2002-05-09 15:18:52 +0000 | [diff] [blame] | 400 | } | 
|  | 401 | Out << ";\n"; | 
|  | 402 | } | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 403 |  | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 404 | // First output all the declarations of the functions as C requires Functions | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 405 | // be declared before they are used. | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 406 | // | 
|  | 407 | Out << "\n\n/* Function Declarations */\n"; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 408 | for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) | 
|  | 409 | printFunctionDecl(I); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 410 |  | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 411 | // Output all of the functions... | 
|  | 412 | Out << "\n\n/* Function Bodies */\n"; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 413 | for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) | 
|  | 414 | printFunction(I); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 415 | } | 
|  | 416 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 417 |  | 
|  | 418 | // printSymbolTable - Run through symbol table looking for named constants | 
|  | 419 | // if a named constant is found, emit it's declaration... | 
|  | 420 | // Assuming that symbol table has only types and constants. | 
|  | 421 | void CWriter::printSymbolTable(const SymbolTable &ST) { | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 422 | for (SymbolTable::const_iterator TI = ST.begin(); TI != ST.end(); ++TI) { | 
|  | 423 | SymbolTable::type_const_iterator I = ST.type_begin(TI->first); | 
|  | 424 | SymbolTable::type_const_iterator End = ST.type_end(TI->first); | 
|  | 425 |  | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 426 | for (; I != End; ++I) | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 427 | if (const Type *Ty = dyn_cast<StructType>(I->second)) { | 
|  | 428 | string Name = "struct l_" + makeNameProper(I->first); | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 429 | Out << Name << ";\n"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 430 |  | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 431 | TypeNames.insert(std::make_pair(Ty, Name)); | 
|  | 432 | } | 
|  | 433 | } | 
|  | 434 |  | 
|  | 435 | Out << "\n"; | 
|  | 436 |  | 
|  | 437 | for (SymbolTable::const_iterator TI = ST.begin(); TI != ST.end(); ++TI) { | 
|  | 438 | SymbolTable::type_const_iterator I = ST.type_begin(TI->first); | 
|  | 439 | SymbolTable::type_const_iterator End = ST.type_end(TI->first); | 
|  | 440 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 441 | for (; I != End; ++I) { | 
|  | 442 | const Value *V = I->second; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 443 | if (const Type *Ty = dyn_cast<Type>(V)) { | 
|  | 444 | string Name = "l_" + makeNameProper(I->first); | 
| Chris Lattner | 1f02c89 | 2002-05-09 20:14:10 +0000 | [diff] [blame] | 445 | if (isa<StructType>(Ty)) | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 446 | Name = "struct " + makeNameProper(Name); | 
| Chris Lattner | 1f02c89 | 2002-05-09 20:14:10 +0000 | [diff] [blame] | 447 | else | 
|  | 448 | Out << "typedef "; | 
|  | 449 |  | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 450 | Out << calcTypeNameVar(Ty, TypeNames, Name, true) << ";\n"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 451 | } | 
|  | 452 | } | 
|  | 453 | } | 
|  | 454 | } | 
|  | 455 |  | 
| Chris Lattner | 3ef6dc7 | 2002-05-09 14:40:11 +0000 | [diff] [blame] | 456 |  | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 457 | // printFunctionDecl - Print function declaration | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 458 | // | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 459 | void CWriter::printFunctionDecl(const Function *F) { | 
|  | 460 | printFunctionSignature(F); | 
|  | 461 | Out << ";\n"; | 
|  | 462 | } | 
|  | 463 |  | 
|  | 464 | void CWriter::printFunctionSignature(const Function *F) { | 
|  | 465 | if (F->hasInternalLinkage()) Out << "static "; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 466 |  | 
|  | 467 | // Loop over the arguments, printing them... | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 468 | const FunctionType *FT = cast<FunctionType>(F->getFunctionType()); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 469 |  | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 470 | // Print out the return type and name... | 
| Chris Lattner | 2a7ab2e | 2002-05-09 04:39:00 +0000 | [diff] [blame] | 471 | printType(F->getReturnType()); | 
| Chris Lattner | 1f02c89 | 2002-05-09 20:14:10 +0000 | [diff] [blame] | 472 | Out << getValueName(F) << "("; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 473 |  | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 474 | if (!F->isExternal()) { | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 475 | if (!F->aempty()) { | 
|  | 476 | printType(F->afront().getType(), getValueName(F->abegin())); | 
| Chris Lattner | deed7a5 | 2002-05-09 15:18:52 +0000 | [diff] [blame] | 477 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 478 | for (Function::const_aiterator I = ++F->abegin(), E = F->aend(); | 
|  | 479 | I != E; ++I) { | 
| Chris Lattner | deed7a5 | 2002-05-09 15:18:52 +0000 | [diff] [blame] | 480 | Out << ", "; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 481 | printType(I->getType(), getValueName(I)); | 
| Chris Lattner | deed7a5 | 2002-05-09 15:18:52 +0000 | [diff] [blame] | 482 | } | 
|  | 483 | } | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 484 | } else { | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 485 | // Loop over the arguments, printing them... | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 486 | for (FunctionType::ParamTypes::const_iterator I = | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 487 | FT->getParamTypes().begin(), | 
|  | 488 | E = FT->getParamTypes().end(); I != E; ++I) { | 
|  | 489 | if (I != FT->getParamTypes().begin()) Out << ", "; | 
| Chris Lattner | 2a7ab2e | 2002-05-09 04:39:00 +0000 | [diff] [blame] | 490 | printType(*I); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 491 | } | 
|  | 492 | } | 
|  | 493 |  | 
|  | 494 | // Finish printing arguments... | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 495 | if (FT->isVarArg()) { | 
|  | 496 | if (FT->getParamTypes().size()) Out << ", "; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 497 | Out << "...";  // Output varargs portion of signature! | 
|  | 498 | } | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 499 | Out << ")"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 500 | } | 
|  | 501 |  | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 502 |  | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 503 | void CWriter::printFunction(Function *F) { | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 504 | if (F->isExternal()) return; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 505 |  | 
| Chris Lattner | f34ee81 | 2002-05-09 03:12:34 +0000 | [diff] [blame] | 506 | Table.incorporateFunction(F); | 
|  | 507 |  | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 508 | printFunctionSignature(F); | 
|  | 509 | Out << " {\n"; | 
|  | 510 |  | 
| Chris Lattner | 497e19a | 2002-05-09 20:39:03 +0000 | [diff] [blame] | 511 | // print local variable information for the function | 
| Chris Lattner | 7683a12 | 2002-05-09 20:33:35 +0000 | [diff] [blame] | 512 | for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 513 | if ((*I)->getType() != Type::VoidTy && !isInlinableInst(**I)) { | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 514 | Out << "  "; | 
| Chris Lattner | 3af3ba8 | 2002-05-09 21:31:18 +0000 | [diff] [blame] | 515 | printType((*I)->getType(), getValueName(*I)); | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 516 | Out << ";\n"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 517 | } | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 518 |  | 
|  | 519 | // print the basic blocks | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 520 | for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { | 
|  | 521 | BasicBlock *Prev = BB->getPrev(); | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 522 |  | 
|  | 523 | // Don't print the label for the basic block if there are no uses, or if the | 
|  | 524 | // only terminator use is the precessor basic block's terminator.  We have | 
|  | 525 | // to scan the use list because PHI nodes use basic blocks too but do not | 
|  | 526 | // require a label to be generated. | 
|  | 527 | // | 
|  | 528 | bool NeedsLabel = false; | 
|  | 529 | for (Value::use_iterator UI = BB->use_begin(), UE = BB->use_end(); | 
|  | 530 | UI != UE; ++UI) | 
|  | 531 | if (TerminatorInst *TI = dyn_cast<TerminatorInst>(*UI)) | 
|  | 532 | if (TI != Prev->getTerminator()) { | 
|  | 533 | NeedsLabel = true; | 
|  | 534 | break; | 
|  | 535 | } | 
|  | 536 |  | 
|  | 537 | if (NeedsLabel) Out << getValueName(BB) << ":\n"; | 
|  | 538 |  | 
|  | 539 | // Output all of the instructions in the basic block... | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 540 | for (BasicBlock::iterator II = BB->begin(), E = --BB->end(); II != E; ++II){ | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 541 | if (!isInlinableInst(*II) && !isa<PHINode>(*II)) { | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 542 | if (II->getType() != Type::VoidTy) | 
|  | 543 | outputLValue(II); | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 544 | else | 
|  | 545 | Out << "  "; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 546 | visit(*II); | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 547 | Out << ";\n"; | 
|  | 548 | } | 
|  | 549 | } | 
|  | 550 |  | 
|  | 551 | // Don't emit prefix or suffix for the terminator... | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 552 | visit(*BB->getTerminator()); | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 553 | } | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 554 |  | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 555 | Out << "}\n\n"; | 
| Chris Lattner | f34ee81 | 2002-05-09 03:12:34 +0000 | [diff] [blame] | 556 | Table.purgeFunction(); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 557 | } | 
|  | 558 |  | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 559 | // Specific Instruction type classes... note that all of the casts are | 
|  | 560 | // neccesary because we use the instruction classes as opaque types... | 
|  | 561 | // | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 562 | void CWriter::visitReturnInst(ReturnInst &I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 563 | // Don't output a void return if this is the last basic block in the function | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 564 | if (I.getNumOperands() == 0 && | 
|  | 565 | &*--I.getParent()->getParent()->end() == I.getParent() && | 
|  | 566 | !I.getParent()->size() == 1) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 567 | return; | 
| Chris Lattner | 963b70b | 2002-05-21 18:05:19 +0000 | [diff] [blame] | 568 | } | 
| Chris Lattner | 4440826 | 2002-05-09 03:50:42 +0000 | [diff] [blame] | 569 |  | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 570 | Out << "  return"; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 571 | if (I.getNumOperands()) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 572 | Out << " "; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 573 | writeOperand(I.getOperand(0)); | 
| Chris Lattner | 16c7bb2 | 2002-05-09 02:28:59 +0000 | [diff] [blame] | 574 | } | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 575 | Out << ";\n"; | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 576 | } | 
|  | 577 |  | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 578 | static bool isGotoCodeNeccessary(BasicBlock *From, BasicBlock *To) { | 
|  | 579 | // If PHI nodes need copies, we need the copy code... | 
|  | 580 | if (isa<PHINode>(To->front()) || | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 581 | From->getNext() != To)      // Not directly successor, need goto | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 582 | return true; | 
|  | 583 |  | 
|  | 584 | // Otherwise we don't need the code. | 
|  | 585 | return false; | 
|  | 586 | } | 
|  | 587 |  | 
|  | 588 | void CWriter::printBranchToBlock(BasicBlock *CurBB, BasicBlock *Succ, | 
|  | 589 | unsigned Indent) { | 
|  | 590 | for (BasicBlock::iterator I = Succ->begin(); | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 591 | PHINode *PN = dyn_cast<PHINode>(&*I); ++I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 592 | //  now we have to do the printing | 
|  | 593 | Out << string(Indent, ' '); | 
|  | 594 | outputLValue(PN); | 
|  | 595 | writeOperand(PN->getIncomingValue(PN->getBasicBlockIndex(CurBB))); | 
|  | 596 | Out << ";   /* for PHI node */\n"; | 
|  | 597 | } | 
|  | 598 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 599 | if (CurBB->getNext() != Succ) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 600 | Out << string(Indent, ' ') << "  goto "; | 
|  | 601 | writeOperand(Succ); | 
|  | 602 | Out << ";\n"; | 
|  | 603 | } | 
|  | 604 | } | 
|  | 605 |  | 
|  | 606 | // Brach instruction printing - Avoid printing out a brach to a basic block that | 
|  | 607 | // immediately succeeds the current one. | 
|  | 608 | // | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 609 | void CWriter::visitBranchInst(BranchInst &I) { | 
|  | 610 | if (I.isConditional()) { | 
|  | 611 | if (isGotoCodeNeccessary(I.getParent(), I.getSuccessor(0))) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 612 | Out << "  if ("; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 613 | writeOperand(I.getCondition()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 614 | Out << ") {\n"; | 
|  | 615 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 616 | printBranchToBlock(I.getParent(), I.getSuccessor(0), 2); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 617 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 618 | if (isGotoCodeNeccessary(I.getParent(), I.getSuccessor(1))) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 619 | Out << "  } else {\n"; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 620 | printBranchToBlock(I.getParent(), I.getSuccessor(1), 2); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 621 | } | 
|  | 622 | } else { | 
|  | 623 | // First goto not neccesary, assume second one is... | 
|  | 624 | Out << "  if (!"; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 625 | writeOperand(I.getCondition()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 626 | Out << ") {\n"; | 
|  | 627 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 628 | printBranchToBlock(I.getParent(), I.getSuccessor(1), 2); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 629 | } | 
|  | 630 |  | 
|  | 631 | Out << "  }\n"; | 
|  | 632 | } else { | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 633 | printBranchToBlock(I.getParent(), I.getSuccessor(0), 0); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 634 | } | 
|  | 635 | Out << "\n"; | 
|  | 636 | } | 
|  | 637 |  | 
|  | 638 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 639 | void CWriter::visitNot(GenericUnaryInst &I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 640 | Out << "~"; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 641 | writeOperand(I.getOperand(0)); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 642 | } | 
|  | 643 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 644 | void CWriter::visitBinaryOperator(Instruction &I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 645 | // binary instructions, shift instructions, setCond instructions. | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 646 | if (isa<PointerType>(I.getType())) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 647 | Out << "("; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 648 | printType(I.getType()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 649 | Out << ")"; | 
|  | 650 | } | 
|  | 651 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 652 | if (isa<PointerType>(I.getType())) Out << "(long long)"; | 
|  | 653 | writeOperand(I.getOperand(0)); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 654 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 655 | switch (I.getOpcode()) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 656 | case Instruction::Add: Out << " + "; break; | 
|  | 657 | case Instruction::Sub: Out << " - "; break; | 
|  | 658 | case Instruction::Mul: Out << "*"; break; | 
|  | 659 | case Instruction::Div: Out << "/"; break; | 
|  | 660 | case Instruction::Rem: Out << "%"; break; | 
|  | 661 | case Instruction::And: Out << " & "; break; | 
|  | 662 | case Instruction::Or: Out << " | "; break; | 
|  | 663 | case Instruction::Xor: Out << " ^ "; break; | 
|  | 664 | case Instruction::SetEQ: Out << " == "; break; | 
|  | 665 | case Instruction::SetNE: Out << " != "; break; | 
|  | 666 | case Instruction::SetLE: Out << " <= "; break; | 
|  | 667 | case Instruction::SetGE: Out << " >= "; break; | 
|  | 668 | case Instruction::SetLT: Out << " < "; break; | 
|  | 669 | case Instruction::SetGT: Out << " > "; break; | 
|  | 670 | case Instruction::Shl : Out << " << "; break; | 
|  | 671 | case Instruction::Shr : Out << " >> "; break; | 
|  | 672 | default: cerr << "Invalid operator type!" << I; abort(); | 
|  | 673 | } | 
|  | 674 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 675 | if (isa<PointerType>(I.getType())) Out << "(long long)"; | 
|  | 676 | writeOperand(I.getOperand(1)); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 677 | } | 
|  | 678 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 679 | void CWriter::visitCastInst(CastInst &I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 680 | Out << "("; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 681 | printType(I.getType()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 682 | Out << ")"; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 683 | writeOperand(I.getOperand(0)); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 684 | } | 
|  | 685 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 686 | void CWriter::visitCallInst(CallInst &I) { | 
|  | 687 | const PointerType  *PTy   = cast<PointerType>(I.getCalledValue()->getType()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 688 | const FunctionType *FTy   = cast<FunctionType>(PTy->getElementType()); | 
|  | 689 | const Type         *RetTy = FTy->getReturnType(); | 
|  | 690 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 691 | Out << getValueName(I.getOperand(0)) << "("; | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 692 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 693 | if (I.getNumOperands() > 1) { | 
|  | 694 | writeOperand(I.getOperand(1)); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 695 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 696 | for (unsigned op = 2, Eop = I.getNumOperands(); op != Eop; ++op) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 697 | Out << ", "; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 698 | writeOperand(I.getOperand(op)); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 699 | } | 
|  | 700 | } | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 701 | Out << ")"; | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 702 | } | 
|  | 703 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 704 | void CWriter::visitMallocInst(MallocInst &I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 705 | Out << "("; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 706 | printType(I.getType()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 707 | Out << ")malloc(sizeof("; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 708 | printType(I.getType()->getElementType()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 709 | Out << ")"; | 
|  | 710 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 711 | if (I.isArrayAllocation()) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 712 | Out << " * " ; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 713 | writeOperand(I.getOperand(0)); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 714 | } | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 715 | Out << ")"; | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 716 | } | 
|  | 717 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 718 | void CWriter::visitAllocaInst(AllocaInst &I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 719 | Out << "("; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 720 | printType(I.getType()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 721 | Out << ") alloca(sizeof("; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 722 | printType(I.getType()->getElementType()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 723 | Out << ")"; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 724 | if (I.isArrayAllocation()) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 725 | Out << " * " ; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 726 | writeOperand(I.getOperand(0)); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 727 | } | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 728 | Out << ")"; | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 729 | } | 
|  | 730 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 731 | void CWriter::visitFreeInst(FreeInst &I) { | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 732 | Out << "free("; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 733 | writeOperand(I.getOperand(0)); | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 734 | Out << ")"; | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 735 | } | 
|  | 736 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 737 | void CWriter::printIndexingExpr(MemAccessInst &MAI) { | 
|  | 738 | MemAccessInst::op_iterator I = MAI.idx_begin(), E = MAI.idx_end(); | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 739 | if (I == E) { | 
|  | 740 | // If accessing a global value with no indexing, avoid *(&GV) syndrome | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 741 | if (GlobalValue *V = dyn_cast<GlobalValue>(MAI.getPointerOperand())) { | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 742 | writeOperandInternal(V); | 
|  | 743 | return; | 
|  | 744 | } | 
|  | 745 |  | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 746 | Out << "*";  // Implicit zero first argument: '*x' is equivalent to 'x[0]' | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 747 | } | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 748 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 749 | writeOperand(MAI.getPointerOperand()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 750 |  | 
|  | 751 | if (I == E) return; | 
|  | 752 |  | 
|  | 753 | // Print out the -> operator if possible... | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 754 | const Constant *CI = dyn_cast<Constant>(I->get()); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 755 | if (CI && CI->isNullValue() && I+1 != E && | 
|  | 756 | (*(I+1))->getType() == Type::UByteTy) { | 
| Chris Lattner | d0c668c | 2002-05-09 21:18:38 +0000 | [diff] [blame] | 757 | Out << "->field" << cast<ConstantUInt>(*(I+1))->getValue(); | 
|  | 758 | I += 2; | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 759 | } | 
|  | 760 |  | 
|  | 761 | for (; I != E; ++I) | 
|  | 762 | if ((*I)->getType() == Type::UIntTy) { | 
|  | 763 | Out << "["; | 
|  | 764 | writeOperand(*I); | 
|  | 765 | Out << "]"; | 
|  | 766 | } else { | 
|  | 767 | Out << ".field" << cast<ConstantUInt>(*I)->getValue(); | 
|  | 768 | } | 
|  | 769 | } | 
|  | 770 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 771 | void CWriter::visitLoadInst(LoadInst &I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 772 | printIndexingExpr(I); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 773 | } | 
|  | 774 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 775 | void CWriter::visitStoreInst(StoreInst &I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 776 | printIndexingExpr(I); | 
|  | 777 | Out << " = "; | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 778 | writeOperand(I.getOperand(0)); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 779 | } | 
|  | 780 |  | 
| Chris Lattner | bb03efd | 2002-06-25 15:57:03 +0000 | [diff] [blame^] | 781 | void CWriter::visitGetElementPtrInst(GetElementPtrInst &I) { | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 782 | Out << "&"; | 
|  | 783 | printIndexingExpr(I); | 
| Chris Lattner | 4fbf26d | 2002-05-09 20:53:56 +0000 | [diff] [blame] | 784 | } | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 785 |  | 
|  | 786 | //===----------------------------------------------------------------------===// | 
|  | 787 | //                       External Interface declaration | 
|  | 788 | //===----------------------------------------------------------------------===// | 
|  | 789 |  | 
| Chris Lattner | f34ee81 | 2002-05-09 03:12:34 +0000 | [diff] [blame] | 790 | void WriteToC(const Module *M, ostream &Out) { | 
|  | 791 | assert(M && "You can't write a null module!!"); | 
|  | 792 | SlotCalculator SlotTable(M, false); | 
|  | 793 | CWriter W(Out, SlotTable, M); | 
| Chris Lattner | 8c3c4bf | 2002-05-09 15:49:41 +0000 | [diff] [blame] | 794 | W.write((Module*)M); | 
| Sumant Kowshik | 9ddc86c | 2002-05-08 18:09:58 +0000 | [diff] [blame] | 795 | Out.flush(); | 
|  | 796 | } |