xref: /llvm-project/llvm/lib/CodeGen/MachineInstr.cpp (revision 7f74a56e2436c40b18a672ad7d58727cd6832329)
1 // $Id$
2 //***************************************************************************
3 // File:
4 //	MachineInstr.cpp
5 //
6 // Purpose:
7 //
8 //
9 // Strategy:
10 //
11 // History:
12 //	7/2/01	 -  Vikram Adve  -  Created
13 //**************************************************************************/
14 
15 
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/Target/MachineFrameInfo.h"
18 #include "llvm/Target/MachineRegInfo.h"
19 #include "llvm/Target/MachineCacheInfo.h"
20 #include "llvm/Method.h"
21 #include "llvm/iOther.h"
22 #include "llvm/Instruction.h"
23 #include <iostream>
24 using std::cerr;
25 
26 AnnotationID MachineCodeForMethod::AID(
27                  AnnotationManager::getID("MachineCodeForMethodAnnotation"));
28 
29 
30 //************************ Class Implementations **************************/
31 
32 // Constructor for instructions with fixed #operands (nearly all)
33 MachineInstr::MachineInstr(MachineOpCode _opCode,
34 			   OpCodeMask    _opCodeMask)
35   : opCode(_opCode),
36     opCodeMask(_opCodeMask),
37     operands(TargetInstrDescriptors[_opCode].numOperands)
38 {
39   assert(TargetInstrDescriptors[_opCode].numOperands >= 0);
40 }
41 
42 // Constructor for instructions with variable #operands
43 MachineInstr::MachineInstr(MachineOpCode _opCode,
44 			   unsigned	 numOperands,
45 			   OpCodeMask    _opCodeMask)
46   : opCode(_opCode),
47     opCodeMask(_opCodeMask),
48     operands(numOperands)
49 {
50 }
51 
52 void
53 MachineInstr::SetMachineOperand(unsigned int i,
54 				MachineOperand::MachineOperandType operandType,
55 				Value* _val, bool isdef=false)
56 {
57   assert(i < operands.size());
58   operands[i].Initialize(operandType, _val);
59   operands[i].isDef = isdef ||
60     TargetInstrDescriptors[opCode].resultPos == (int) i;
61 }
62 
63 void
64 MachineInstr::SetMachineOperand(unsigned int i,
65 				MachineOperand::MachineOperandType operandType,
66 				int64_t intValue, bool isdef=false)
67 {
68   assert(i < operands.size());
69   operands[i].InitializeConst(operandType, intValue);
70   operands[i].isDef = isdef ||
71     TargetInstrDescriptors[opCode].resultPos == (int) i;
72 }
73 
74 void
75 MachineInstr::SetMachineOperand(unsigned int i,
76 				int regNum, bool isdef=false)
77 {
78   assert(i < operands.size());
79   operands[i].InitializeReg(regNum);
80   operands[i].isDef = isdef ||
81     TargetInstrDescriptors[opCode].resultPos == (int) i;
82 }
83 
84 void
85 MachineInstr::dump(unsigned int indent) const
86 {
87   for (unsigned i=0; i < indent; i++)
88     cerr << "    ";
89 
90   cerr << *this;
91 }
92 
93 std::ostream &operator<<(std::ostream& os, const MachineInstr& minstr)
94 {
95   os << TargetInstrDescriptors[minstr.opCode].opCodeString;
96 
97   for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++) {
98     os << "\t" << minstr.getOperand(i);
99     if( minstr.getOperand(i).opIsDef() )
100       os << "*";
101   }
102 
103 #undef DEBUG_VAL_OP_ITERATOR
104 #ifdef DEBUG_VAL_OP_ITERATOR
105   os << "\n\tValue operands are: ";
106   for (MachineInstr::val_const_op_iterator vo(&minstr); ! vo.done(); ++vo)
107     {
108       const Value* val = *vo;
109       os << val << (vo.isDef()? "(def), " : ", ");
110     }
111 #endif
112 
113 
114 
115 #if 1
116   // code for printing implict references
117 
118   unsigned NumOfImpRefs =  minstr.getNumImplicitRefs();
119   if(  NumOfImpRefs > 0 ) {
120 
121     os << "\tImplicit:";
122 
123     for(unsigned z=0; z < NumOfImpRefs; z++) {
124       os << minstr.getImplicitRef(z);
125       if( minstr.implicitRefIsDefined(z)) os << "*";
126       os << "\t";
127     }
128   }
129 
130 #endif
131   return os << "\n";
132 }
133 
134 static inline std::ostream &OutputOperand(std::ostream &os,
135                                           const MachineOperand &mop)
136 {
137   Value* val;
138   switch (mop.getOperandType())
139     {
140     case MachineOperand::MO_CCRegister:
141     case MachineOperand::MO_VirtualRegister:
142       val = mop.getVRegValue();
143       os << "(val ";
144       if (val && val->hasName())
145         os << val->getName();
146       else
147         os << val;
148       return os << ")";
149     case MachineOperand::MO_MachineRegister:
150       return os << "("     << mop.getMachineRegNum() << ")";
151     default:
152       assert(0 && "Unknown operand type");
153       return os;
154     }
155 }
156 
157 
158 std::ostream &operator<<(std::ostream &os, const MachineOperand &mop)
159 {
160   switch(mop.opType)
161     {
162     case MachineOperand::MO_VirtualRegister:
163     case MachineOperand::MO_MachineRegister:
164       os << "%reg";
165       return OutputOperand(os, mop);
166     case MachineOperand::MO_CCRegister:
167       os << "%ccreg";
168       return OutputOperand(os, mop);
169     case MachineOperand::MO_SignExtendedImmed:
170       return os << (long)mop.immedVal;
171     case MachineOperand::MO_UnextendedImmed:
172       return os << (long)mop.immedVal;
173     case MachineOperand::MO_PCRelativeDisp:
174       {
175         const Value* opVal = mop.getVRegValue();
176         bool isLabel = isa<Method>(opVal) || isa<BasicBlock>(opVal);
177         os << "%disp(" << (isLabel? "label " : "addr-of-val ");
178         if (opVal->hasName())
179           os << opVal->getName();
180         else
181           os << opVal;
182         return os << ")";
183       }
184     default:
185       assert(0 && "Unrecognized operand type");
186       break;
187     }
188 
189   return os;
190 }
191 
192 // Align data larger than one L1 cache line on L1 cache line boundaries.
193 // Align all smaller data on the next higher 2^x boundary (4, 8, ...).
194 //
195 // THIS FUNCTION HAS BEEN COPIED FROM EMITASSEMBLY.CPP AND
196 // SHOULD BE USED DIRECTLY THERE
197 //
198 inline unsigned int
199 SizeToAlignment(unsigned int size, const TargetMachine& target)
200 {
201   unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
202   if (size > (unsigned) cacheLineSize / 2)
203     return cacheLineSize;
204   else
205     for (unsigned sz=1; /*no condition*/; sz *= 2)
206       if (sz >= size)
207         return sz;
208 }
209 
210 static unsigned int
211 ComputeMaxOptionalArgsSize(const TargetMachine& target, const Method* method)
212 {
213   const MachineFrameInfo& frameInfo = target.getFrameInfo();
214 
215   unsigned int maxSize = 0;
216 
217   for (Method::const_inst_iterator I=method->inst_begin(),E=method->inst_end();
218        I != E; ++I)
219     if ((*I)->getOpcode() == Instruction::Call)
220       {
221         CallInst* callInst = cast<CallInst>(*I);
222         unsigned int numOperands = callInst->getNumOperands() - 1;
223         int numExtra = (int) numOperands - frameInfo.getNumFixedOutgoingArgs();
224         if (numExtra <= 0)
225           continue;
226 
227         unsigned int sizeForThisCall;
228         if (frameInfo.argsOnStackHaveFixedSize())
229           {
230             int argSize = frameInfo.getSizeOfEachArgOnStack();
231             sizeForThisCall = numExtra * (unsigned) argSize;
232           }
233         else
234           {
235             assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual arg sizes to compute MaxOptionalArgsSize");
236             sizeForThisCall = 0;
237             for (unsigned i=0; i < numOperands; ++i)
238               sizeForThisCall += target.findOptimalStorageSize(callInst->
239                                                     getOperand(i)->getType());
240           }
241 
242         if (maxSize < sizeForThisCall)
243           maxSize = sizeForThisCall;
244       }
245 
246   return maxSize;
247 }
248 
249 
250 /*ctor*/
251 MachineCodeForMethod::MachineCodeForMethod(const Method* _M,
252                                            const TargetMachine& target)
253   : Annotation(AID),
254     method(_M), compiledAsLeaf(false), staticStackSize(0),
255     automaticVarsSize(0), regSpillsSize(0),
256     currentOptionalArgsSize(0), maxOptionalArgsSize(0),
257     currentTmpValuesSize(0)
258 {
259   maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method);
260   staticStackSize = maxOptionalArgsSize +
261                     target.getFrameInfo().getMinStackFrameSize();
262 }
263 
264 int
265 MachineCodeForMethod::allocateLocalVar(const TargetMachine& target,
266                                        const Value* val,
267                                        unsigned int size)
268 {
269   // Check if we've allocated a stack slot for this value already
270   //
271   int offset = getOffset(val);
272   if (offset == INVALID_FRAME_OFFSET)
273     {
274       bool growUp;
275       int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this,
276                                                                        growUp);
277       unsigned char align;
278       if (size == 0)
279         {
280           size  = target.findOptimalStorageSize(val->getType());
281           // align = target.DataLayout.getTypeAlignment(val->getType());
282         }
283 
284       align = SizeToAlignment(size, target);
285 
286       offset = getAutomaticVarsSize();
287       if (! growUp)
288         offset += size;
289 
290       if (unsigned int mod = offset % align)
291         {
292           offset += align - mod;
293           size   += align - mod;
294         }
295 
296       offset = growUp? firstOffset + offset
297                      : firstOffset - offset;
298 
299       offsets[val] = offset;
300 
301       incrementAutomaticVarsSize(size);
302     }
303   return offset;
304 }
305 
306 int
307 MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target,
308                                            const Type* type)
309 {
310   unsigned int size  = target.findOptimalStorageSize(type);
311   unsigned char align = target.DataLayout.getTypeAlignment(type);
312 
313   bool growUp;
314   int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp);
315 
316   int offset = getRegSpillsSize();
317   if (! growUp)
318     offset += size;
319 
320   if (unsigned int mod = offset % align)
321     {
322       offset    += align - mod;
323       size += align - mod;
324     }
325 
326   offset = growUp? firstOffset + offset
327                  : firstOffset - offset;
328 
329   incrementRegSpillsSize(size);
330 
331   return offset;
332 }
333 
334 int
335 MachineCodeForMethod::allocateOptionalArg(const TargetMachine& target,
336                                           const Type* type)
337 {
338   const MachineFrameInfo& frameInfo = target.getFrameInfo();
339 
340   int size = MAXINT;
341   if (frameInfo.argsOnStackHaveFixedSize())
342     size = frameInfo.getSizeOfEachArgOnStack();
343   else
344     {
345       size = target.findOptimalStorageSize(type);
346       assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual argument sizes for computing optional arg offsets");
347     }
348   unsigned char align = target.DataLayout.getTypeAlignment(type);
349 
350   bool growUp;
351   int firstOffset = frameInfo.getFirstOptionalOutgoingArgOffset(*this, growUp);
352 
353   int offset = getCurrentOptionalArgsSize();
354   if (! growUp)
355     offset += size;
356 
357   if (unsigned int mod = offset % align)
358     {
359       offset += align - mod;
360       size   += align - mod;
361     }
362 
363   offset = growUp? firstOffset + offset
364                  : firstOffset - offset;
365 
366   incrementCurrentOptionalArgsSize(size);
367 
368   return offset;
369 }
370 
371 void
372 MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target)
373 {
374   currentOptionalArgsSize = 0;
375 }
376 
377 int
378 MachineCodeForMethod::pushTempValue(const TargetMachine& target,
379                                     unsigned int size)
380 {
381   // Compute a power-of-2 alignment according to the possible sizes,
382   // but not greater than the alignment of the largest type we support
383   // (currently a double word -- see class TargetData).
384   unsigned char align = 1;
385   for (; align < size && align < target.DataLayout.getDoubleAlignment();
386          align = 2*align)
387     ;
388 
389   bool growUp;
390   int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp);
391 
392   int offset = currentTmpValuesSize;
393   if (! growUp)
394     offset += size;
395 
396   if (unsigned int mod = offset % align)
397     {
398       offset += align - mod;
399       size   += align - mod;
400     }
401 
402   offset = growUp ? firstTmpOffset + offset : firstTmpOffset - offset;
403 
404   currentTmpValuesSize += size;
405   return offset;
406 }
407 
408 void
409 MachineCodeForMethod::popAllTempValues(const TargetMachine& target)
410 {
411   currentTmpValuesSize = 0;
412 }
413 
414 int
415 MachineCodeForMethod::getOffset(const Value* val) const
416 {
417   std::hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
418   return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second;
419 }
420 
421 void
422 MachineCodeForMethod::dump() const
423 {
424   cerr << "\n" << method->getReturnType()
425        << " \"" << method->getName() << "\"\n";
426 
427   for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI)
428     {
429       BasicBlock* bb = *BI;
430       cerr << "\n"
431 	   << (bb->hasName()? bb->getName() : "Label")
432 	   << " (" << bb << ")" << ":\n";
433 
434       MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
435       for (unsigned i=0; i < mvec.size(); i++)
436 	cerr << "\t" << *mvec[i];
437     }
438   cerr << "\nEnd method \"" << method->getName() << "\"\n\n";
439 }
440