aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/X86/Printer.cpp
blob: 8bf9968c0620a7f97d1034a899df8f971fa8d35f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//===-- X86/Printer.cpp - Convert X86 code to human readable rep. ---------===//
//
// This file contains a printer that converts from our internal representation
// of LLVM code to a nice human readable form that is suitable for debuggging.
//
//===----------------------------------------------------------------------===//

#include "X86.h"
#include "X86InstrInfo.h"
#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"

namespace {
  struct Printer : public FunctionPass {
    TargetMachine &TM;
    std::ostream &O;

    Printer(TargetMachine &tm, std::ostream &o) : TM(tm), O(o) {}

    bool runOnFunction(Function &F);
  };
}

/// createX86CodePrinterPass - Print out the specified machine code function to
/// the specified stream.  This function should work regardless of whether or
/// not the function is in SSA form or not.
///
Pass *createX86CodePrinterPass(TargetMachine &TM, std::ostream &O) {
  return new Printer(TM, O);
}


/// runOnFunction - This uses the X86InstructionInfo::print method
/// to print assembly for each instruction.
bool Printer::runOnFunction (Function & F)
{
  static unsigned bbnumber = 0;
  MachineFunction & MF = MachineFunction::get (&F);
  const MachineInstrInfo & MII = TM.getInstrInfo ();

  O << "; x86 printing only sorta implemented so far!\n";

  // Print out labels for the function.
  O << "\t.globl\t" << F.getName () << "\n";
  O << "\t.type\t" << F.getName () << ", @function\n";
  O << F.getName () << ":\n";

  // Print out code for the function.
  for (MachineFunction::const_iterator bb_i = MF.begin (), bb_e = MF.end ();
       bb_i != bb_e; ++bb_i)
    {
      // Print a label for the basic block.
      O << ".BB" << bbnumber++ << ":\n";
      for (MachineBasicBlock::const_iterator i_i = bb_i->begin (), i_e =
	   bb_i->end (); i_i != i_e; ++i_i)
	{
	  // Print the assembly for the instruction.
	  O << "\t";
          MII.print(*i_i, O, TM);
	}
    }

  // We didn't modify anything.
  return false;
}

static void printOp(std::ostream &O, const MachineOperand &MO,
                    const MRegisterInfo &RI) {
  switch (MO.getType()) {
  case MachineOperand::MO_VirtualRegister:
  case MachineOperand::MO_MachineRegister:
    if (MO.getReg() < MRegisterInfo::FirstVirtualRegister)
      O << RI.get(MO.getReg()).Name;
    else
      O << "%reg" << MO.getReg();
    return;
    
  default:
    O << "<unknown op ty>"; return;    
  }
}

static inline void toHexDigit(std::ostream &O, unsigned char V) {
  if (V >= 10)
    O << (char)('A'+V-10);
  else
    O << (char)('0'+V);
}

static std::ostream &toHex(std::ostream &O, unsigned char V) {
  toHexDigit(O, V >> 4);
  toHexDigit(O, V & 0xF);
  return O;
}


// print - Print out an x86 instruction in intel syntax
void X86InstrInfo::print(const MachineInstr *MI, std::ostream &O,
                         const TargetMachine &TM) const {
  unsigned Opcode = MI->getOpcode();
  const MachineInstrDescriptor &Desc = get(Opcode);

  if (Desc.TSFlags & X86II::TB)
    O << "0F ";

  switch (Desc.TSFlags & X86II::FormMask) {
  case X86II::OtherFrm:
    O << "\t";
    O << "-"; MI->print(O, TM);
    break;
  case X86II::RawFrm:
    toHex(O, getBaseOpcodeFor(Opcode)) << "\t";
    O << getName(MI->getOpCode()) << " ";

    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      if (i) O << ", ";
      printOp(O, MI->getOperand(i), RI);
    }
    O << "\n";
    return;


  case X86II::AddRegFrm:
    O << "\t-"; MI->print(O, TM); break;

  case X86II::MRMDestReg:
    // There are two acceptable forms of MRMDestReg instructions, those with 3
    // and 2 operands:
    //
    // 3 Operands: in this form, the first two registers (the destination, and
    // the first operand) should be the same, post register allocation.  The 3rd
    // operand is an additional input.  This should be for things like add
    // instructions.
    //
    // 2 Operands: this is for things like mov that do not read a second input
    //
    assert(((MI->getNumOperands() == 3 && 
             (MI->getOperand(0).getType()==MachineOperand::MO_VirtualRegister||
              MI->getOperand(0).getType()==MachineOperand::MO_MachineRegister)
             &&
             (MI->getOperand(1).getType()==MachineOperand::MO_VirtualRegister||
              MI->getOperand(1).getType()==MachineOperand::MO_MachineRegister))
            ||
            (MI->getNumOperands() == 2 && 
             (MI->getOperand(0).getType()==MachineOperand::MO_VirtualRegister||
              MI->getOperand(0).getType()==MachineOperand::MO_MachineRegister)
             && (MI->getOperand(MI->getNumOperands()-1).getType() ==
                 MachineOperand::MO_VirtualRegister||
                 MI->getOperand(MI->getNumOperands()-1).getType() ==
                 MachineOperand::MO_MachineRegister)))
           && "Bad format for MRMDestReg!");
    if (MI->getNumOperands() == 3 &&
        MI->getOperand(0).getReg() != MI->getOperand(1).getReg())
      O << "**";

    O << "\t";
    O << getName(MI->getOpCode()) << " ";
    printOp(O, MI->getOperand(0), RI);
    O << ", ";
    printOp(O, MI->getOperand(MI->getNumOperands()-1), RI);
    O << "\n";
    return;
  case X86II::MRMDestMem:
  case X86II::MRMSrcReg:
  case X86II::MRMSrcMem:
  default:
    O << "\t-"; MI->print(O, TM); break;
  }
}