1193323Sed//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// CodeEmitterGen uses the descriptions of instructions and their fields to
11193323Sed// construct an automated code emitter: a function that, given a MachineInstr,
12193323Sed// returns the (currently, 32-bit unsigned) value of the instruction.
13193323Sed//
14193323Sed//===----------------------------------------------------------------------===//
15193323Sed
16193323Sed#include "CodeGenTarget.h"
17193323Sed#include "llvm/ADT/StringExtras.h"
18218893Sdim#include "llvm/Support/CommandLine.h"
19193323Sed#include "llvm/Support/Debug.h"
20249423Sdim#include "llvm/TableGen/Record.h"
21239462Sdim#include "llvm/TableGen/TableGenBackend.h"
22218893Sdim#include <map>
23239462Sdim#include <string>
24239462Sdim#include <vector>
25193323Sedusing namespace llvm;
26193323Sed
27218893Sdim// FIXME: Somewhat hackish to use a command line option for this. There should
28218893Sdim// be a CodeEmitter class in the Target.td that controls this sort of thing
29218893Sdim// instead.
30218893Sdimstatic cl::opt<bool>
31218893SdimMCEmitter("mc-emitter",
32218893Sdim          cl::desc("Generate CodeEmitter for use with the MC library."),
33218893Sdim          cl::init(false));
34218893Sdim
35239462Sdimnamespace {
36239462Sdim
37239462Sdimclass CodeEmitterGen {
38239462Sdim  RecordKeeper &Records;
39239462Sdimpublic:
40239462Sdim  CodeEmitterGen(RecordKeeper &R) : Records(R) {}
41239462Sdim
42239462Sdim  void run(raw_ostream &o);
43239462Sdimprivate:
44239462Sdim  void emitMachineOpEmitter(raw_ostream &o, const std::string &Namespace);
45239462Sdim  void emitGetValueBit(raw_ostream &o, const std::string &Namespace);
46239462Sdim  void reverseBits(std::vector<Record*> &Insts);
47239462Sdim  int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
48239462Sdim  std::string getInstructionCase(Record *R, CodeGenTarget &Target);
49239462Sdim  void AddCodeToMergeInOperand(Record *R, BitsInit *BI,
50239462Sdim                               const std::string &VarName,
51239462Sdim                               unsigned &NumberedOp,
52239462Sdim                               std::string &Case, CodeGenTarget &Target);
53239462Sdim
54239462Sdim};
55239462Sdim
56193323Sedvoid CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
57193323Sed  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
58193323Sed       I != E; ++I) {
59193323Sed    Record *R = *I;
60224145Sdim    if (R->getValueAsString("Namespace") == "TargetOpcode" ||
61224145Sdim        R->getValueAsBit("isPseudo"))
62210299Sed      continue;
63193323Sed
64193323Sed    BitsInit *BI = R->getValueAsBitsInit("Inst");
65193323Sed
66193323Sed    unsigned numBits = BI->getNumBits();
67226633Sdim
68226633Sdim    SmallVector<Init *, 16> NewBits(numBits);
69226633Sdim
70193323Sed    for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
71193323Sed      unsigned bitSwapIdx = numBits - bit - 1;
72193323Sed      Init *OrigBit = BI->getBit(bit);
73193323Sed      Init *BitSwap = BI->getBit(bitSwapIdx);
74226633Sdim      NewBits[bit]        = BitSwap;
75226633Sdim      NewBits[bitSwapIdx] = OrigBit;
76193323Sed    }
77193323Sed    if (numBits % 2) {
78193323Sed      unsigned middle = (numBits + 1) / 2;
79226633Sdim      NewBits[middle] = BI->getBit(middle);
80193323Sed    }
81218893Sdim
82226633Sdim    BitsInit *NewBI = BitsInit::get(NewBits);
83226633Sdim
84193323Sed    // Update the bits in reversed order so that emitInstrOpBits will get the
85193323Sed    // correct endianness.
86193323Sed    R->getValue("Inst")->setValue(NewBI);
87193323Sed  }
88193323Sed}
89193323Sed
90193323Sed// If the VarBitInit at position 'bit' matches the specified variable then
91193323Sed// return the variable bit position.  Otherwise return -1.
92201360Srdivackyint CodeEmitterGen::getVariableBit(const std::string &VarName,
93218893Sdim                                   BitsInit *BI, int bit) {
94243830Sdim  if (VarBitInit *VBI = dyn_cast<VarBitInit>(BI->getBit(bit))) {
95243830Sdim    if (VarInit *VI = dyn_cast<VarInit>(VBI->getBitVar()))
96218893Sdim      if (VI->getName() == VarName)
97218893Sdim        return VBI->getBitNum();
98243830Sdim  } else if (VarInit *VI = dyn_cast<VarInit>(BI->getBit(bit))) {
99221345Sdim    if (VI->getName() == VarName)
100221345Sdim      return 0;
101221345Sdim  }
102218893Sdim
103218893Sdim  return -1;
104218893Sdim}
105218893Sdim
106218893Sdimvoid CodeEmitterGen::
107218893SdimAddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
108218893Sdim                        unsigned &NumberedOp,
109218893Sdim                        std::string &Case, CodeGenTarget &Target) {
110218893Sdim  CodeGenInstruction &CGI = Target.getInstruction(R);
111218893Sdim
112218893Sdim  // Determine if VarName actually contributes to the Inst encoding.
113218893Sdim  int bit = BI->getNumBits()-1;
114218893Sdim
115218893Sdim  // Scan for a bit that this contributed to.
116218893Sdim  for (; bit >= 0; ) {
117218893Sdim    if (getVariableBit(VarName, BI, bit) != -1)
118218893Sdim      break;
119201360Srdivacky
120218893Sdim    --bit;
121218893Sdim  }
122218893Sdim
123218893Sdim  // If we found no bits, ignore this value, otherwise emit the call to get the
124218893Sdim  // operand encoding.
125218893Sdim  if (bit < 0) return;
126218893Sdim
127218893Sdim  // If the operand matches by name, reference according to that
128218893Sdim  // operand number. Non-matching operands are assumed to be in
129218893Sdim  // order.
130218893Sdim  unsigned OpIdx;
131218893Sdim  if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
132218893Sdim    // Get the machine operand number for the indicated operand.
133218893Sdim    OpIdx = CGI.Operands[OpIdx].MIOperandNo;
134218893Sdim    assert(!CGI.Operands.isFlatOperandNotEmitted(OpIdx) &&
135218893Sdim           "Explicitly used operand also marked as not emitted!");
136218893Sdim  } else {
137243830Sdim    unsigned NumberOps = CGI.Operands.size();
138218893Sdim    /// If this operand is not supposed to be emitted by the
139218893Sdim    /// generated emitter, skip it.
140243830Sdim    while (NumberedOp < NumberOps &&
141243830Sdim           CGI.Operands.isFlatOperandNotEmitted(NumberedOp))
142218893Sdim      ++NumberedOp;
143243830Sdim
144218893Sdim    OpIdx = NumberedOp++;
145218893Sdim  }
146218893Sdim
147218893Sdim  std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx);
148218893Sdim  std::string &EncoderMethodName = CGI.Operands[SO.first].EncoderMethodName;
149218893Sdim
150218893Sdim  // If the source operand has a custom encoder, use it. This will
151218893Sdim  // get the encoding for all of the suboperands.
152218893Sdim  if (!EncoderMethodName.empty()) {
153218893Sdim    // A custom encoder has all of the information for the
154218893Sdim    // sub-operands, if there are more than one, so only
155218893Sdim    // query the encoder once per source operand.
156218893Sdim    if (SO.second == 0) {
157218893Sdim      Case += "      // op: " + VarName + "\n" +
158218893Sdim              "      op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
159218893Sdim      if (MCEmitter)
160218893Sdim        Case += ", Fixups";
161218893Sdim      Case += ");\n";
162201360Srdivacky    }
163218893Sdim  } else {
164218893Sdim    Case += "      // op: " + VarName + "\n" +
165218893Sdim      "      op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
166218893Sdim    if (MCEmitter)
167218893Sdim      Case += ", Fixups";
168218893Sdim    Case += ");\n";
169193323Sed  }
170193323Sed
171218893Sdim  for (; bit >= 0; ) {
172218893Sdim    int varBit = getVariableBit(VarName, BI, bit);
173218893Sdim
174218893Sdim    // If this bit isn't from a variable, skip it.
175218893Sdim    if (varBit == -1) {
176218893Sdim      --bit;
177218893Sdim      continue;
178218893Sdim    }
179218893Sdim
180218893Sdim    // Figure out the consecutive range of bits covered by this operand, in
181218893Sdim    // order to generate better encoding code.
182218893Sdim    int beginInstBit = bit;
183218893Sdim    int beginVarBit = varBit;
184218893Sdim    int N = 1;
185218893Sdim    for (--bit; bit >= 0;) {
186218893Sdim      varBit = getVariableBit(VarName, BI, bit);
187218893Sdim      if (varBit == -1 || varBit != (beginVarBit - N)) break;
188218893Sdim      ++N;
189218893Sdim      --bit;
190218893Sdim    }
191218893Sdim
192234353Sdim    uint64_t opMask = ~(uint64_t)0 >> (64-N);
193218893Sdim    int opShift = beginVarBit - N + 1;
194218893Sdim    opMask <<= opShift;
195218893Sdim    opShift = beginInstBit - beginVarBit;
196218893Sdim
197218893Sdim    if (opShift > 0) {
198234353Sdim      Case += "      Value |= (op & UINT64_C(" + utostr(opMask) + ")) << " +
199218893Sdim              itostr(opShift) + ";\n";
200218893Sdim    } else if (opShift < 0) {
201234353Sdim      Case += "      Value |= (op & UINT64_C(" + utostr(opMask) + ")) >> " +
202218893Sdim              itostr(-opShift) + ";\n";
203218893Sdim    } else {
204234353Sdim      Case += "      Value |= op & UINT64_C(" + utostr(opMask) + ");\n";
205218893Sdim    }
206218893Sdim  }
207218893Sdim}
208193323Sed
209193323Sed
210218893Sdimstd::string CodeEmitterGen::getInstructionCase(Record *R,
211218893Sdim                                               CodeGenTarget &Target) {
212218893Sdim  std::string Case;
213218893Sdim
214218893Sdim  BitsInit *BI = R->getValueAsBitsInit("Inst");
215218893Sdim  const std::vector<RecordVal> &Vals = R->getValues();
216218893Sdim  unsigned NumberedOp = 0;
217218893Sdim
218218893Sdim  // Loop over all of the fields in the instruction, determining which are the
219218893Sdim  // operands to the instruction.
220218893Sdim  for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
221218893Sdim    // Ignore fixed fields in the record, we're looking for values like:
222218893Sdim    //    bits<5> RST = { ?, ?, ?, ?, ? };
223218893Sdim    if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete())
224218893Sdim      continue;
225218893Sdim
226218893Sdim    AddCodeToMergeInOperand(R, BI, Vals[i].getName(), NumberedOp, Case, Target);
227218893Sdim  }
228218893Sdim
229218893Sdim  std::string PostEmitter = R->getValueAsString("PostEncoderMethod");
230218893Sdim  if (!PostEmitter.empty())
231218893Sdim    Case += "      Value = " + PostEmitter + "(MI, Value);\n";
232218893Sdim
233218893Sdim  return Case;
234218893Sdim}
235218893Sdim
236195340Sedvoid CodeEmitterGen::run(raw_ostream &o) {
237218893Sdim  CodeGenTarget Target(Records);
238193323Sed  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
239218893Sdim
240193323Sed  // For little-endian instruction bit encodings, reverse the bit order
241193323Sed  if (Target.isLittleEndianEncoding()) reverseBits(Insts);
242193323Sed
243218893Sdim
244205407Srdivacky  const std::vector<const CodeGenInstruction*> &NumberedInstructions =
245205407Srdivacky    Target.getInstructionsByEnumValue();
246193323Sed
247193323Sed  // Emit function declaration
248234353Sdim  o << "uint64_t " << Target.getName();
249218893Sdim  if (MCEmitter)
250218893Sdim    o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
251218893Sdim      << "    SmallVectorImpl<MCFixup> &Fixups) const {\n";
252218893Sdim  else
253218893Sdim    o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n";
254193323Sed
255193323Sed  // Emit instruction base values
256234353Sdim  o << "  static const uint64_t InstBits[] = {\n";
257205407Srdivacky  for (std::vector<const CodeGenInstruction*>::const_iterator
258193323Sed          IN = NumberedInstructions.begin(),
259193323Sed          EN = NumberedInstructions.end();
260193323Sed       IN != EN; ++IN) {
261193323Sed    const CodeGenInstruction *CGI = *IN;
262193323Sed    Record *R = CGI->TheDef;
263218893Sdim
264224145Sdim    if (R->getValueAsString("Namespace") == "TargetOpcode" ||
265224145Sdim        R->getValueAsBit("isPseudo")) {
266234353Sdim      o << "    UINT64_C(0),\n";
267193323Sed      continue;
268193323Sed    }
269218893Sdim
270193323Sed    BitsInit *BI = R->getValueAsBitsInit("Inst");
271193323Sed
272218893Sdim    // Start by filling in fixed values.
273234353Sdim    uint64_t Value = 0;
274193323Sed    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
275243830Sdim      if (BitInit *B = dyn_cast<BitInit>(BI->getBit(e-i-1)))
276234353Sdim        Value |= (uint64_t)B->getValue() << (e-i-1);
277193323Sed    }
278234353Sdim    o << "    UINT64_C(" << Value << ")," << '\t' << "// " << R->getName() << "\n";
279193323Sed  }
280234353Sdim  o << "    UINT64_C(0)\n  };\n";
281218893Sdim
282193323Sed  // Map to accumulate all the cases.
283193323Sed  std::map<std::string, std::vector<std::string> > CaseMap;
284218893Sdim
285193323Sed  // Construct all cases statement for each opcode
286193323Sed  for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
287193323Sed        IC != EC; ++IC) {
288193323Sed    Record *R = *IC;
289224145Sdim    if (R->getValueAsString("Namespace") == "TargetOpcode" ||
290224145Sdim        R->getValueAsBit("isPseudo"))
291210299Sed      continue;
292218893Sdim    const std::string &InstName = R->getValueAsString("Namespace") + "::"
293218893Sdim      + R->getName();
294218893Sdim    std::string Case = getInstructionCase(R, Target);
295193323Sed
296218893Sdim    CaseMap[Case].push_back(InstName);
297193323Sed  }
298193323Sed
299193323Sed  // Emit initial function code
300193323Sed  o << "  const unsigned opcode = MI.getOpcode();\n"
301234353Sdim    << "  uint64_t Value = InstBits[opcode];\n"
302234353Sdim    << "  uint64_t op = 0;\n"
303218893Sdim    << "  (void)op;  // suppress warning\n"
304193323Sed    << "  switch (opcode) {\n";
305193323Sed
306193323Sed  // Emit each case statement
307193323Sed  std::map<std::string, std::vector<std::string> >::iterator IE, EE;
308193323Sed  for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
309193323Sed    const std::string &Case = IE->first;
310193323Sed    std::vector<std::string> &InstList = IE->second;
311193323Sed
312193323Sed    for (int i = 0, N = InstList.size(); i < N; i++) {
313193323Sed      if (i) o << "\n";
314218893Sdim      o << "    case " << InstList[i]  << ":";
315193323Sed    }
316193323Sed    o << " {\n";
317193323Sed    o << Case;
318193323Sed    o << "      break;\n"
319193323Sed      << "    }\n";
320193323Sed  }
321193323Sed
322193323Sed  // Default case: unhandled opcode
323193323Sed  o << "  default:\n"
324198090Srdivacky    << "    std::string msg;\n"
325198090Srdivacky    << "    raw_string_ostream Msg(msg);\n"
326198090Srdivacky    << "    Msg << \"Not supported instr: \" << MI;\n"
327207618Srdivacky    << "    report_fatal_error(Msg.str());\n"
328193323Sed    << "  }\n"
329193323Sed    << "  return Value;\n"
330193323Sed    << "}\n\n";
331193323Sed}
332239462Sdim
333239462Sdim} // End anonymous namespace
334239462Sdim
335239462Sdimnamespace llvm {
336239462Sdim
337239462Sdimvoid EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS) {
338239462Sdim  emitSourceFileHeader("Machine Code Emitter", OS);
339239462Sdim  CodeEmitterGen(RK).run(OS);
340239462Sdim}
341239462Sdim
342239462Sdim} // End llvm namespace
343