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