| Chris Lattner | f2868ce | 2002-02-03 07:54:50 +0000 | [diff] [blame] | 1 | //===-- MachineCodeForMethod.cpp --------------------------------------------=// | 
 | 2 | //  | 
 | 3 | // Purpose: | 
 | 4 | //   Collect native machine code information for a method. | 
 | 5 | //   This allows target-specific information about the generated code | 
 | 6 | //   to be stored with each method. | 
 | 7 | //===----------------------------------------------------------------------===// | 
 | 8 |  | 
 | 9 | #include "llvm/CodeGen/MachineCodeForMethod.h" | 
 | 10 | #include "llvm/CodeGen/MachineInstr.h"  // For debug output | 
 | 11 | #include "llvm/Target/TargetMachine.h" | 
 | 12 | #include "llvm/Target/MachineFrameInfo.h" | 
 | 13 | #include "llvm/Target/MachineCacheInfo.h" | 
 | 14 | #include "llvm/Method.h" | 
 | 15 | #include "llvm/iOther.h" | 
 | 16 | #include <limits.h> | 
 | 17 |  | 
 | 18 | const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max(); | 
 | 19 |  | 
 | 20 | static AnnotationID MCFM_AID( | 
 | 21 |                  AnnotationManager::getID("CodeGen::MachineCodeForMethod")); | 
 | 22 |  | 
 | 23 | // The next two methods are used to construct and to retrieve | 
 | 24 | // the MachineCodeForMethod object for the given method. | 
 | 25 | // construct() -- Allocates and initializes for a given method and target | 
 | 26 | // get()       -- Returns a handle to the object. | 
 | 27 | //                This should not be called before "construct()" | 
 | 28 | //                for a given Method. | 
 | 29 | //  | 
 | 30 | MachineCodeForMethod &MachineCodeForMethod::construct(const Method *M, | 
 | 31 |                                                       const TargetMachine &Tar){ | 
 | 32 |   assert(M->getAnnotation(MCFM_AID) == 0 && | 
 | 33 |          "Object already exists for this method!"); | 
 | 34 |   MachineCodeForMethod* mcInfo = new MachineCodeForMethod(M, Tar); | 
 | 35 |   M->addAnnotation(mcInfo); | 
 | 36 |   return *mcInfo; | 
 | 37 | } | 
 | 38 |  | 
 | 39 | void MachineCodeForMethod::destruct(const Method *M) { | 
 | 40 |   bool Deleted = M->deleteAnnotation(MCFM_AID); | 
 | 41 |   assert(Deleted && "Machine code did not exist for method!"); | 
 | 42 | } | 
 | 43 |  | 
 | 44 |  | 
 | 45 | MachineCodeForMethod &MachineCodeForMethod::get(const Method* method) { | 
 | 46 |   MachineCodeForMethod* mc = (MachineCodeForMethod*) | 
 | 47 |     method->getAnnotation(MCFM_AID); | 
 | 48 |   assert(mc && "Call construct() method first to allocate the object"); | 
 | 49 |   return *mc; | 
 | 50 | } | 
 | 51 |  | 
 | 52 | static unsigned | 
 | 53 | ComputeMaxOptionalArgsSize(const TargetMachine& target, const Method* method) | 
 | 54 | { | 
 | 55 |   const MachineFrameInfo& frameInfo = target.getFrameInfo(); | 
 | 56 |    | 
 | 57 |   unsigned int maxSize = 0; | 
 | 58 |    | 
 | 59 |   for (Method::const_inst_iterator I=method->inst_begin(),E=method->inst_end(); | 
 | 60 |        I != E; ++I) | 
 | 61 |     if ((*I)->getOpcode() == Instruction::Call) | 
 | 62 |       { | 
 | 63 |         CallInst* callInst = cast<CallInst>(*I); | 
 | 64 |         unsigned int numOperands = callInst->getNumOperands() - 1; | 
 | 65 |         int numExtra = (int) numOperands - frameInfo.getNumFixedOutgoingArgs(); | 
 | 66 |         if (numExtra <= 0) | 
 | 67 |           continue; | 
 | 68 |          | 
 | 69 |         unsigned int sizeForThisCall; | 
 | 70 |         if (frameInfo.argsOnStackHaveFixedSize()) | 
 | 71 |           { | 
 | 72 |             int argSize = frameInfo.getSizeOfEachArgOnStack();  | 
 | 73 |             sizeForThisCall = numExtra * (unsigned) argSize; | 
 | 74 |           } | 
 | 75 |         else | 
 | 76 |           { | 
 | 77 |             assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual arg sizes to compute MaxOptionalArgsSize"); | 
 | 78 |             sizeForThisCall = 0; | 
 | 79 |             for (unsigned i=0; i < numOperands; ++i) | 
 | 80 |               sizeForThisCall += target.findOptimalStorageSize(callInst-> | 
 | 81 |                                                     getOperand(i)->getType()); | 
 | 82 |           } | 
 | 83 |          | 
 | 84 |         if (maxSize < sizeForThisCall) | 
 | 85 |           maxSize = sizeForThisCall; | 
 | 86 |       } | 
 | 87 |    | 
 | 88 |   return maxSize; | 
 | 89 | } | 
 | 90 |  | 
 | 91 | // Align data larger than one L1 cache line on L1 cache line boundaries. | 
 | 92 | // Align all smaller data on the next higher 2^x boundary (4, 8, ...). | 
 | 93 | // | 
 | 94 | // THIS FUNCTION HAS BEEN COPIED FROM EMITASSEMBLY.CPP AND | 
 | 95 | // SHOULD BE USED DIRECTLY THERE | 
 | 96 | //  | 
 | 97 | inline unsigned int | 
 | 98 | SizeToAlignment(unsigned int size, const TargetMachine& target) | 
 | 99 | { | 
 | 100 |   unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);  | 
 | 101 |   if (size > (unsigned) cacheLineSize / 2) | 
 | 102 |     return cacheLineSize; | 
 | 103 |   else | 
 | 104 |     for (unsigned sz=1; /*no condition*/; sz *= 2) | 
 | 105 |       if (sz >= size) | 
 | 106 |         return sz; | 
 | 107 | } | 
 | 108 |  | 
 | 109 |  | 
 | 110 |  | 
 | 111 | /*ctor*/ | 
 | 112 | MachineCodeForMethod::MachineCodeForMethod(const Method* _M, | 
 | 113 |                                            const TargetMachine& target) | 
 | 114 |   : Annotation(MCFM_AID), | 
 | 115 |     method(_M), compiledAsLeaf(false), staticStackSize(0), | 
 | 116 |     automaticVarsSize(0), regSpillsSize(0), | 
 | 117 |     currentOptionalArgsSize(0), maxOptionalArgsSize(0), | 
 | 118 |     currentTmpValuesSize(0) | 
 | 119 | { | 
 | 120 |   maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method); | 
 | 121 |   staticStackSize = maxOptionalArgsSize + | 
 | 122 |                     target.getFrameInfo().getMinStackFrameSize(); | 
 | 123 | } | 
 | 124 |  | 
 | 125 | int | 
 | 126 | MachineCodeForMethod::allocateLocalVar(const TargetMachine& target, | 
 | 127 |                                        const Value* val, | 
 | 128 |                                        unsigned int size) | 
 | 129 | { | 
 | 130 |   // Check if we've allocated a stack slot for this value already | 
 | 131 |   //  | 
 | 132 |   int offset = getOffset(val); | 
 | 133 |   if (offset == INVALID_FRAME_OFFSET) | 
 | 134 |     { | 
 | 135 |       bool growUp; | 
 | 136 |       int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this, | 
 | 137 |                                                                        growUp); | 
 | 138 |       unsigned char align; | 
 | 139 |       if (size == 0) | 
 | 140 |         { | 
 | 141 |           size  = target.findOptimalStorageSize(val->getType()); | 
 | 142 |           // align = target.DataLayout.getTypeAlignment(val->getType()); | 
 | 143 |         } | 
 | 144 |        | 
 | 145 |       align = SizeToAlignment(size, target); | 
 | 146 |            | 
 | 147 |       offset = getAutomaticVarsSize(); | 
 | 148 |       if (! growUp) | 
 | 149 |         offset += size;  | 
 | 150 |        | 
 | 151 |       if (unsigned int mod = offset % align) | 
 | 152 |         { | 
 | 153 |           offset += align - mod; | 
 | 154 |           size   += align - mod; | 
 | 155 |         } | 
 | 156 |        | 
 | 157 |       offset = growUp? firstOffset + offset | 
 | 158 |                      : firstOffset - offset; | 
 | 159 |        | 
 | 160 |       offsets[val] = offset; | 
 | 161 |        | 
 | 162 |       incrementAutomaticVarsSize(size); | 
 | 163 |     } | 
 | 164 |   return offset; | 
 | 165 | } | 
 | 166 |  | 
 | 167 | int | 
 | 168 | MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target, | 
 | 169 |                                            const Type* type) | 
 | 170 | { | 
 | 171 |   unsigned int size  = target.findOptimalStorageSize(type); | 
 | 172 |   unsigned char align = target.DataLayout.getTypeAlignment(type); | 
 | 173 |    | 
 | 174 |   bool growUp; | 
 | 175 |   int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp); | 
 | 176 |    | 
 | 177 |   int offset = getRegSpillsSize(); | 
 | 178 |   if (! growUp) | 
 | 179 |     offset += size;  | 
 | 180 |    | 
 | 181 |   if (unsigned int mod = offset % align) | 
 | 182 |     { | 
 | 183 |       offset    += align - mod; | 
 | 184 |       size += align - mod; | 
 | 185 |     } | 
 | 186 |    | 
 | 187 |   offset = growUp? firstOffset + offset | 
 | 188 |                  : firstOffset - offset; | 
 | 189 |    | 
 | 190 |   incrementRegSpillsSize(size); | 
 | 191 |    | 
 | 192 |   return offset; | 
 | 193 | } | 
 | 194 |  | 
 | 195 | int | 
 | 196 | MachineCodeForMethod::allocateOptionalArg(const TargetMachine& target, | 
 | 197 |                                           const Type* type) | 
 | 198 | { | 
 | 199 |   const MachineFrameInfo& frameInfo = target.getFrameInfo(); | 
 | 200 |    | 
 | 201 |   int size = INT_MAX; | 
 | 202 |   if (frameInfo.argsOnStackHaveFixedSize()) | 
 | 203 |     size = frameInfo.getSizeOfEachArgOnStack();  | 
 | 204 |   else | 
 | 205 |     { | 
 | 206 |       size = target.findOptimalStorageSize(type); | 
 | 207 |       assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual argument sizes for computing optional arg offsets"); | 
 | 208 |     } | 
 | 209 |   unsigned char align = target.DataLayout.getTypeAlignment(type); | 
 | 210 |    | 
 | 211 |   bool growUp; | 
 | 212 |   int firstOffset = frameInfo.getFirstOptionalOutgoingArgOffset(*this, growUp); | 
 | 213 |    | 
 | 214 |   int offset = getCurrentOptionalArgsSize(); | 
 | 215 |   if (! growUp) | 
 | 216 |     offset += size;  | 
 | 217 |    | 
 | 218 |   if (unsigned int mod = offset % align) | 
 | 219 |     { | 
 | 220 |       offset += align - mod; | 
 | 221 |       size   += align - mod; | 
 | 222 |     } | 
 | 223 |    | 
 | 224 |   offset = growUp? firstOffset + offset | 
 | 225 |                  : firstOffset - offset; | 
 | 226 |    | 
 | 227 |   incrementCurrentOptionalArgsSize(size); | 
 | 228 |    | 
 | 229 |   return offset; | 
 | 230 | } | 
 | 231 |  | 
 | 232 | void | 
 | 233 | MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target) | 
 | 234 | { | 
 | 235 |   currentOptionalArgsSize = 0; | 
 | 236 | } | 
 | 237 |  | 
 | 238 | int | 
 | 239 | MachineCodeForMethod::pushTempValue(const TargetMachine& target, | 
 | 240 |                                     unsigned int size) | 
 | 241 | { | 
 | 242 |   // Compute a power-of-2 alignment according to the possible sizes, | 
 | 243 |   // but not greater than the alignment of the largest type we support | 
 | 244 |   // (currently a double word -- see class TargetData). | 
 | 245 |   unsigned char align = 1; | 
 | 246 |   for (; align < size && align < target.DataLayout.getDoubleAlignment(); | 
 | 247 |          align = 2*align) | 
 | 248 |     ; | 
 | 249 |    | 
 | 250 |   bool growUp; | 
 | 251 |   int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp); | 
 | 252 |    | 
 | 253 |   int offset = currentTmpValuesSize; | 
 | 254 |   if (! growUp) | 
 | 255 |     offset += size;  | 
 | 256 |    | 
 | 257 |   if (unsigned int mod = offset % align) | 
 | 258 |     { | 
 | 259 |       offset += align - mod; | 
 | 260 |       size   += align - mod; | 
 | 261 |     } | 
 | 262 |    | 
 | 263 |   offset = growUp ? firstTmpOffset + offset : firstTmpOffset - offset; | 
 | 264 |    | 
 | 265 |   currentTmpValuesSize += size; | 
 | 266 |   return offset; | 
 | 267 | } | 
 | 268 |  | 
 | 269 | void | 
 | 270 | MachineCodeForMethod::popAllTempValues(const TargetMachine& target) | 
 | 271 | { | 
 | 272 |   currentTmpValuesSize = 0; | 
 | 273 | } | 
 | 274 |  | 
 | 275 | int | 
 | 276 | MachineCodeForMethod::getOffset(const Value* val) const | 
 | 277 | { | 
 | 278 |   std::hash_map<const Value*, int>::const_iterator pair = offsets.find(val); | 
 | 279 |   return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second; | 
 | 280 | } | 
 | 281 |  | 
 | 282 | void | 
 | 283 | MachineCodeForMethod::dump() const | 
 | 284 | { | 
 | 285 |   cerr << "\n" << method->getReturnType() | 
 | 286 |        << " \"" << method->getName() << "\"\n"; | 
 | 287 |    | 
 | 288 |   for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI) | 
 | 289 |     { | 
 | 290 |       BasicBlock* bb = *BI; | 
 | 291 |       cerr << "\n" | 
 | 292 | 	   << (bb->hasName()? bb->getName() : "Label") | 
 | 293 | 	   << " (" << bb << ")" << ":\n"; | 
 | 294 |  | 
 | 295 |       MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec(); | 
 | 296 |       for (unsigned i=0; i < mvec.size(); i++) | 
 | 297 | 	cerr << "\t" << *mvec[i]; | 
 | 298 |     }  | 
 | 299 |   cerr << "\nEnd method \"" << method->getName() << "\"\n\n"; | 
 | 300 | } |