blob: a9b0c60acc16121b136fa3f72a39bc98456f089d [file] [log] [blame]
Chris Lattner40ead952002-12-02 21:24:12 +00001//===-- X86/MachineCodeEmitter.cpp - Convert X86 code to machine code -----===//
2//
3// This file contains the pass that transforms the X86 machine instructions into
4// actual executable machine code.
5//
6//===----------------------------------------------------------------------===//
7
8#include "X86TargetMachine.h"
9#include "llvm/PassManager.h"
10#include "llvm/CodeGen/MachineCodeEmitter.h"
Chris Lattner76041ce2002-12-02 21:44:34 +000011#include "llvm/CodeGen/MachineFunction.h"
12#include "llvm/CodeGen/MachineInstr.h"
Chris Lattner40ead952002-12-02 21:24:12 +000013
14namespace {
15 struct Emitter : public FunctionPass {
Chris Lattner8f04b092002-12-02 21:56:18 +000016 X86TargetMachine &TM;
17 const X86InstrInfo ⅈ
18 MachineCodeEmitter &MCE;
Chris Lattner40ead952002-12-02 21:24:12 +000019
Chris Lattner8f04b092002-12-02 21:56:18 +000020 Emitter(X86TargetMachine &tm, MachineCodeEmitter &mce)
21 : TM(tm), II(TM.getInstrInfo()), MCE(mce) {}
Chris Lattner40ead952002-12-02 21:24:12 +000022
Chris Lattner76041ce2002-12-02 21:44:34 +000023 bool runOnFunction(Function &F);
24
25 void emitBasicBlock(MachineBasicBlock &MBB);
26 void emitInstruction(MachineInstr &MI);
Chris Lattner40ead952002-12-02 21:24:12 +000027 };
28}
29
30
31/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
32/// machine code emitted. This uses a MAchineCodeEmitter object to handle
33/// actually outputting the machine code and resolving things like the address
34/// of functions. This method should returns true if machine code emission is
35/// not supported.
36///
37bool X86TargetMachine::addPassesToEmitMachineCode(PassManager &PM,
38 MachineCodeEmitter &MCE) {
39 PM.add(new Emitter(*this, MCE));
40 return false;
41}
Chris Lattner76041ce2002-12-02 21:44:34 +000042
43bool Emitter::runOnFunction(Function &F) {
44 MachineFunction &MF = MachineFunction::get(&F);
45
46 MCE.startFunction(MF);
47 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
48 emitBasicBlock(*I);
49 MCE.finishFunction(MF);
50 return false;
51}
52
53void Emitter::emitBasicBlock(MachineBasicBlock &MBB) {
54 MCE.startBasicBlock(MBB);
55 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I)
56 emitInstruction(**I);
57}
58
59void Emitter::emitInstruction(MachineInstr &MI) {
60 unsigned Opcode = MI.getOpcode();
Chris Lattner8f04b092002-12-02 21:56:18 +000061 const MachineInstrDescriptor &Desc = II.get(Opcode);
Chris Lattner76041ce2002-12-02 21:44:34 +000062
63 // Emit instruction prefixes if neccesary
64 if (Desc.TSFlags & X86II::OpSize) MCE.emitByte(0x66);// Operand size...
Chris Lattner8f04b092002-12-02 21:56:18 +000065 if (Desc.TSFlags & X86II::TB) MCE.emitByte(0x0F);// Two-byte opcode prefix
Chris Lattner76041ce2002-12-02 21:44:34 +000066
67 switch (Desc.TSFlags & X86II::FormMask) {
68 case X86II::RawFrm:
Chris Lattner8f04b092002-12-02 21:56:18 +000069 MCE.emitByte(II.getBaseOpcodeFor(Opcode));
70
71 if (MI.getNumOperands() == 1) {
72 assert(MI.getOperand(0).getType() == MachineOperand::MO_PCRelativeDisp);
73 MCE.emitPCRelativeDisp(MI.getOperand(0).getVRegValue());
74 }
75
76 break;
Chris Lattner76041ce2002-12-02 21:44:34 +000077 }
78}