1 //===-- SparcV8CodeEmitter.cpp - JIT Code Emitter for SparcV8 -----*- C++ -*-=//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 //===----------------------------------------------------------------------===//
14 #include "SparcV8TargetMachine.h"
15 #include "llvm/Module.h"
16 #include "llvm/CodeGen/MachineCodeEmitter.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/Passes.h"
19 #include "llvm/Support/Debug.h"
26 class SparcV8CodeEmitter : public MachineFunctionPass {
28 MachineCodeEmitter &MCE;
30 /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
32 int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO);
34 // Tracks which instruction references which BasicBlock
35 std::vector<std::pair<const BasicBlock*,
36 std::pair<unsigned*,MachineInstr*> > > BBRefs;
37 // Tracks where each BasicBlock starts
38 std::map<const BasicBlock*, long> BBLocations;
41 SparcV8CodeEmitter(TargetMachine &T, MachineCodeEmitter &M)
44 const char *getPassName() const { return "SparcV8 Machine Code Emitter"; }
46 /// runOnMachineFunction - emits the given MachineFunction to memory
48 bool runOnMachineFunction(MachineFunction &MF);
50 /// emitBasicBlock - emits the given MachineBasicBlock to memory
52 void emitBasicBlock(MachineBasicBlock &MBB);
54 /// emitWord - write a 32-bit word to memory at the current PC
56 void emitWord(unsigned w) { MCE.emitWord(w); }
58 /// getValueBit - return the particular bit of Val
60 unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; }
62 /// getBinaryCodeForInstr - This function, generated by the
63 /// CodeEmitterGenerator using TableGen, produces the binary encoding for
64 /// machine instructions.
66 unsigned getBinaryCodeForInstr(MachineInstr &MI);
70 /// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
71 /// machine code emitted. This uses a MachineCodeEmitter object to handle
72 /// actually outputting the machine code and resolving things like the address
73 /// of functions. This method should returns true if machine code emission is
76 bool SparcV8TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
77 MachineCodeEmitter &MCE) {
78 // Keep as `true' until this is a functional JIT to allow llvm-gcc to build
81 // Machine code emitter pass for SparcV8
82 PM.add(new SparcV8CodeEmitter(*this, MCE));
83 // Delete machine code for this function after emitting it
84 PM.add(createMachineCodeDeleter());
88 bool SparcV8CodeEmitter::runOnMachineFunction(MachineFunction &MF) {
89 MCE.startFunction(MF);
90 MCE.emitConstantPool(MF.getConstantPool());
91 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
93 MCE.finishFunction(MF);
95 // Resolve branches to BasicBlocks for the entire function
96 for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
97 long Location = BBLocations[BBRefs[i].first];
98 unsigned *Ref = BBRefs[i].second.first;
99 MachineInstr *MI = BBRefs[i].second.second;
100 DEBUG(std::cerr << "Fixup @ " << std::hex << Ref << " to 0x" << Location
101 << " in instr: " << std::dec << *MI);
102 for (unsigned ii = 0, ee = MI->getNumOperands(); ii != ee; ++ii) {
103 MachineOperand &op = MI->getOperand(ii);
104 if (op.isPCRelativeDisp()) {
105 // the instruction's branch target is made such that it branches to
106 // PC + (branchTarget * 4), so undo that arithmetic here:
107 // Location is the target of the branch
108 // Ref is the location of the instruction, and hence the PC
109 int64_t branchTarget = (Location - (long)Ref) >> 2;
110 MI->SetMachineOperandConst(ii, MachineOperand::MO_SignExtendedImmed,
112 unsigned fixedInstr = SparcV8CodeEmitter::getBinaryCodeForInstr(*MI);
113 MCE.emitWordAt(fixedInstr, Ref);
124 void SparcV8CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
125 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I)
126 emitWord(getBinaryCodeForInstr(*I));
129 int64_t SparcV8CodeEmitter::getMachineOpValue(MachineInstr &MI,
130 MachineOperand &MO) {
131 int64_t rv = 0; // Return value; defaults to 0 for unhandled cases
132 // or things that get fixed up later by the JIT.
133 if (MO.isPCRelativeDisp()) {
134 std::cerr << "SparcV8CodeEmitter: PC-relative disp unhandled\n";
136 } else if (MO.isRegister()) {
138 } else if (MO.isImmediate()) {
139 rv = MO.getImmedValue();
140 } else if (MO.isGlobalAddress()) {
141 GlobalValue *GV = MO.getGlobal();
142 std::cerr << "Unhandled global value: " << GV << "\n";
144 } else if (MO.isMachineBasicBlock()) {
145 const BasicBlock *BB = MO.getMachineBasicBlock()->getBasicBlock();
146 unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
147 BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI)));
148 } else if (MO.isExternalSymbol()) {
149 } else if (MO.isConstantPoolIndex()) {
150 unsigned index = MO.getConstantPoolIndex();
151 rv = MCE.getConstantPoolEntryAddress(index);
152 } else if (MO.isFrameIndex()) {
153 std::cerr << "SparcV8CodeEmitter: error: Frame index unhandled!\n";
156 std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
160 // Adjust for special meaning of operands in some instructions
161 unsigned Opcode = MI.getOpcode();
162 if (Opcode == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) {
164 } else if (Opcode == V8::ORri &&!MO.isRegister() &&!MO.isImmediate()) {
165 rv = (rv >> 10) & 0x03fffff;
171 void *SparcV8JITInfo::getJITStubForFunction(Function *F,
172 MachineCodeEmitter &MCE) {
173 std::cerr << "SparcV8JITInfo::getJITStubForFunction not implemented!\n";
178 void SparcV8JITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
179 std::cerr << "SparcV8JITInfo::replaceMachineCodeForFunction not implemented!";
183 #include "SparcV8GenCodeEmitter.inc"