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