MachineInstr.cpp revision 56786d268feeb6d0e895b6c4cba60139285c47d6
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/Method.h"
18#include "llvm/ConstPoolVals.h"
19#include "llvm/Instruction.h"
20#include <strstream>
21
22
23//************************ Class Implementations **************************/
24
25// Constructor for instructions with fixed #operands (nearly all)
26MachineInstr::MachineInstr(MachineOpCode _opCode,
27			   OpCodeMask    _opCodeMask)
28  : opCode(_opCode),
29    opCodeMask(_opCodeMask),
30    operands(TargetInstrDescriptors[_opCode].numOperands)
31{
32  assert(TargetInstrDescriptors[_opCode].numOperands >= 0);
33}
34
35// Constructor for instructions with variable #operands
36MachineInstr::MachineInstr(MachineOpCode _opCode,
37			   unsigned	 numOperands,
38			   OpCodeMask    _opCodeMask)
39  : opCode(_opCode),
40    opCodeMask(_opCodeMask),
41    operands(numOperands)
42{
43}
44
45void
46MachineInstr::SetMachineOperand(unsigned int i,
47				MachineOperand::MachineOperandType operandType,
48				Value* _val, bool isdef=false)
49{
50  assert(i < operands.size());
51  operands[i].Initialize(operandType, _val);
52  operands[i].isDef = isdef ||
53		      TargetInstrDescriptors[opCode].resultPos == (int) i;
54}
55
56void
57MachineInstr::SetMachineOperand(unsigned int i,
58				MachineOperand::MachineOperandType operandType,
59				int64_t intValue, bool isdef=false)
60{
61  assert(i < operands.size());
62  operands[i].InitializeConst(operandType, intValue);
63  operands[i].isDef = isdef ||
64		      TargetInstrDescriptors[opCode].resultPos == (int) i;
65}
66
67void
68MachineInstr::SetMachineOperand(unsigned int i,
69				unsigned int regNum, bool isdef=false)
70{
71  assert(i < operands.size());
72  operands[i].InitializeReg(regNum);
73  operands[i].isDef = isdef ||
74		      TargetInstrDescriptors[opCode].resultPos == (int) i;
75}
76
77void
78MachineInstr::dump(unsigned int indent) const
79{
80  for (unsigned i=0; i < indent; i++)
81    cout << "    ";
82
83  cout << *this;
84}
85
86ostream&
87operator<< (ostream& os, const MachineInstr& minstr)
88{
89  os << TargetInstrDescriptors[minstr.opCode].opCodeString;
90
91  for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++)
92    os << "\t" << minstr.getOperand(i);
93
94#undef DEBUG_VAL_OP_ITERATOR
95#ifdef DEBUG_VAL_OP_ITERATOR
96  os << endl << "\tValue operands are: ";
97  for (MachineInstr::val_op_const_iterator vo(&minstr); ! vo.done(); ++vo)
98    {
99      const Value* val = *vo;
100      os << val << (vo.isDef()? "(def), " : ", ");
101    }
102  os << endl;
103#endif
104
105  return os;
106}
107
108ostream&
109operator<< (ostream& os, const MachineOperand& mop)
110{
111  strstream regInfo;
112  if (mop.opType == MachineOperand::MO_VirtualRegister)
113    regInfo << "(val " << mop.value << ")" << ends;
114  else if (mop.opType == MachineOperand::MO_MachineRegister)
115    regInfo << "("       << mop.regNum << ")" << ends;
116  else if (mop.opType == MachineOperand::MO_CCRegister)
117    regInfo << "(val " << mop.value << ")" << ends;
118
119  switch(mop.opType)
120    {
121    case MachineOperand::MO_VirtualRegister:
122    case MachineOperand::MO_MachineRegister:
123      os << "%reg" << regInfo.str();
124      free(regInfo.str());
125      break;
126
127    case MachineOperand::MO_CCRegister:
128      os << "%ccreg" << regInfo.str();
129      free(regInfo.str());
130      break;
131
132    case MachineOperand::MO_SignExtendedImmed:
133      os << mop.immedVal;
134      break;
135
136    case MachineOperand::MO_UnextendedImmed:
137      os << mop.immedVal;
138      break;
139
140    case MachineOperand::MO_PCRelativeDisp:
141      os << "%disp(label " << mop.value << ")";
142      break;
143
144    default:
145      assert(0 && "Unrecognized operand type");
146      break;
147    }
148
149  return os;
150}
151
152
153//---------------------------------------------------------------------------
154// Target-independent utility routines for creating machine instructions
155//---------------------------------------------------------------------------
156
157
158//------------------------------------------------------------------------
159// Function Set2OperandsFromInstr
160// Function Set3OperandsFromInstr
161//
162// For the common case of 2- and 3-operand arithmetic/logical instructions,
163// set the m/c instr. operands directly from the VM instruction's operands.
164// Check whether the first or second operand is 0 and can use a dedicated "0" register.
165// Check whether the second operand should use an immediate field or register.
166// (First and third operands are never immediates for such instructions.)
167//
168// Arguments:
169// canDiscardResult: Specifies that the result operand can be discarded
170//		     by using the dedicated "0"
171//
172// op1position, op2position and resultPosition: Specify in which position
173//		     in the machine instruction the 3 operands (arg1, arg2
174//		     and result) should go.
175//
176// RETURN VALUE: unsigned int flags, where
177//	flags & 0x01	=> operand 1 is constant and needs a register
178//	flags & 0x02	=> operand 2 is constant and needs a register
179//------------------------------------------------------------------------
180
181void
182Set2OperandsFromInstr(MachineInstr* minstr,
183		      InstructionNode* vmInstrNode,
184		      const TargetMachine& target,
185		      bool canDiscardResult,
186		      int op1Position,
187		      int resultPosition)
188{
189  Set3OperandsFromInstr(minstr, vmInstrNode, target,
190			canDiscardResult, op1Position,
191			/*op2Position*/ -1, resultPosition);
192}
193
194#undef REVERT_TO_EXPLICIT_CONSTANT_CHECKS
195#ifdef REVERT_TO_EXPLICIT_CONSTANT_CHECKS
196unsigned
197Set3OperandsFromInstrJUNK(MachineInstr* minstr,
198		      InstructionNode* vmInstrNode,
199		      const TargetMachine& target,
200		      bool canDiscardResult,
201		      int op1Position,
202		      int op2Position,
203		      int resultPosition)
204{
205  assert(op1Position >= 0);
206  assert(resultPosition >= 0);
207
208  unsigned returnFlags = 0x0;
209
210  // Check if operand 1 is 0.  If so, try to use a hardwired 0 register.
211  Value* op1Value = vmInstrNode->leftChild()->getValue();
212  bool isValidConstant;
213  int64_t intValue = GetConstantValueAsSignedInt(op1Value, isValidConstant);
214  if (isValidConstant && intValue == 0 && target.zeroRegNum >= 0)
215    minstr->SetMachineOperand(op1Position, /*regNum*/ target.zeroRegNum);
216  else
217    {
218      if (op1Value->getValueType() == Value::ConstantVal)
219	{// value is constant and must be loaded from constant pool
220	  returnFlags = returnFlags | (1 << op1Position);
221	}
222      minstr->SetMachineOperand(op1Position,MachineOperand::MO_VirtualRegister,
223					    op1Value);
224    }
225
226  // Check if operand 2 (if any) fits in the immed. field of the instruction,
227  // or if it is 0 and can use a dedicated machine register
228  if (op2Position >= 0)
229    {
230      Value* op2Value = vmInstrNode->rightChild()->getValue();
231      int64_t immedValue;
232      unsigned int machineRegNum;
233
234      MachineOperand::MachineOperandType
235	op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(), target,
236				   /*canUseImmed*/ true,
237				   machineRegNum, immedValue);
238
239      if (op2type == MachineOperand::MO_MachineRegister)
240	minstr->SetMachineOperand(op2Position, machineRegNum);
241      else if (op2type == MachineOperand::MO_VirtualRegister)
242	{
243	  if (op2Value->getValueType() == Value::ConstantVal)
244	    {// value is constant and must be loaded from constant pool
245	      returnFlags = returnFlags | (1 << op2Position);
246	    }
247	  minstr->SetMachineOperand(op2Position, op2type, op2Value);
248	}
249      else
250	{
251	  assert(op2type != MO_CCRegister);
252	  minstr->SetMachineOperand(op2Position, op2type, immedValue);
253	}
254    }
255
256  // If operand 3 (result) can be discarded, use a dead register if one exists
257  if (canDiscardResult && target.zeroRegNum >= 0)
258    minstr->SetMachineOperand(resultPosition, target.zeroRegNum);
259  else
260    minstr->SetMachineOperand(resultPosition, MachineOperand::MO_VirtualRegister, vmInstrNode->getValue());
261
262  return returnFlags;
263}
264#endif
265
266
267void
268Set3OperandsFromInstr(MachineInstr* minstr,
269		      InstructionNode* vmInstrNode,
270		      const TargetMachine& target,
271		      bool canDiscardResult,
272		      int op1Position,
273		      int op2Position,
274		      int resultPosition)
275{
276  assert(op1Position >= 0);
277  assert(resultPosition >= 0);
278
279  // operand 1
280  minstr->SetMachineOperand(op1Position, MachineOperand::MO_VirtualRegister,
281			    vmInstrNode->leftChild()->getValue());
282
283  // operand 2 (if any)
284  if (op2Position >= 0)
285    minstr->SetMachineOperand(op2Position, MachineOperand::MO_VirtualRegister,
286			      vmInstrNode->rightChild()->getValue());
287
288  // result operand: if it can be discarded, use a dead register if one exists
289  if (canDiscardResult && target.zeroRegNum >= 0)
290    minstr->SetMachineOperand(resultPosition, target.zeroRegNum);
291  else
292    minstr->SetMachineOperand(resultPosition, MachineOperand::MO_VirtualRegister, vmInstrNode->getValue());
293}
294
295
296MachineOperand::MachineOperandType
297ChooseRegOrImmed(Value* val,
298		 MachineOpCode opCode,
299		 const TargetMachine& target,
300		 bool canUseImmed,
301		 unsigned int& getMachineRegNum,
302		 int64_t& getImmedValue)
303{
304  MachineOperand::MachineOperandType opType =
305    MachineOperand::MO_VirtualRegister;
306  getMachineRegNum = 0;
307  getImmedValue = 0;
308
309  // Check for the common case first: argument is not constant
310  //
311  if (val->getValueType() != Value::ConstantVal)
312    return opType;
313
314  // Now get the constant value and check if it fits in the IMMED field.
315  // Take advantage of the fact that the max unsigned value will rarely
316  // fit into any IMMED field and ignore that case (i.e., cast smaller
317  // unsigned constants to signed).
318  //
319  bool isValidConstant;
320  int64_t intValue = GetConstantValueAsSignedInt(val, isValidConstant);
321
322  if (isValidConstant)
323    {
324      if (intValue == 0 && target.zeroRegNum >= 0)
325	{
326	  opType = MachineOperand::MO_MachineRegister;
327	  getMachineRegNum = target.zeroRegNum;
328	}
329      else if (canUseImmed &&
330	       target.getInstrInfo().constantFitsInImmedField(opCode,intValue))
331	{
332	  opType = MachineOperand::MO_SignExtendedImmed;
333	  getImmedValue = intValue;
334	}
335    }
336
337  return opType;
338}
339
340
341void
342PrintMachineInstructions(const Method* method)
343{
344  cout << "\n" << method->getReturnType()
345       << " \"" << method->getName() << "\"" << endl;
346
347  for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI)
348    {
349      const BasicBlock* bb = *BI;
350      cout << "\n"
351	   << (bb->hasName()? bb->getName() : "Label")
352	   << " (" << bb << ")" << ":"
353	   << endl;
354
355      const MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
356      for (unsigned i=0; i < mvec.size(); i++)
357	cout << "\t" << *mvec[i] << endl;
358    }
359  cout << endl << "End method \"" << method->getName() << "\""
360       << endl << endl;
361}
362