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"
27 class SparcV8CodeEmitter : public MachineFunctionPass {
29 MachineCodeEmitter &MCE;
31 /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
33 int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO);
35 // Tracks which instruction references which BasicBlock
36 std::vector<std::pair<const BasicBlock*,
37 std::pair<unsigned*,MachineInstr*> > > BBRefs;
38 // Tracks where each BasicBlock starts
39 std::map<const BasicBlock*, long> BBLocations;
42 SparcV8CodeEmitter(TargetMachine &T, MachineCodeEmitter &M)
45 const char *getPassName() const { return "SparcV8 Machine Code Emitter"; }
47 /// runOnMachineFunction - emits the given MachineFunction to memory
49 bool runOnMachineFunction(MachineFunction &MF);
51 /// emitBasicBlock - emits the given MachineBasicBlock to memory
53 void emitBasicBlock(MachineBasicBlock &MBB);
55 /// emitWord - write a 32-bit word to memory at the current PC
57 void emitWord(unsigned w) { MCE.emitWord(w); }
59 /// getValueBit - return the particular bit of Val
61 unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; }
63 /// getBinaryCodeForInstr - This function, generated by the
64 /// CodeEmitterGenerator using TableGen, produces the binary encoding for
65 /// machine instructions.
67 unsigned getBinaryCodeForInstr(MachineInstr &MI);
71 /// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
72 /// machine code emitted. This uses a MachineCodeEmitter object to handle
73 /// actually outputting the machine code and resolving things like the address
74 /// of functions. This method should returns true if machine code emission is
77 bool SparcV8TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
78 MachineCodeEmitter &MCE) {
79 // Keep as `true' until this is a functional JIT to allow llvm-gcc to build
82 // Machine code emitter pass for SparcV8
83 PM.add(new SparcV8CodeEmitter(*this, MCE));
84 // Delete machine code for this function after emitting it
85 PM.add(createMachineCodeDeleter());
89 bool SparcV8CodeEmitter::runOnMachineFunction(MachineFunction &MF) {
90 MCE.startFunction(MF);
91 MCE.emitConstantPool(MF.getConstantPool());
92 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
94 MCE.finishFunction(MF);
96 // Resolve branches to BasicBlocks for the entire function
97 for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
98 long Location = BBLocations[BBRefs[i].first];
99 unsigned *Ref = BBRefs[i].second.first;
100 MachineInstr *MI = BBRefs[i].second.second;
101 DEBUG(std::cerr << "Fixup @ " << std::hex << Ref << " to 0x" << Location
102 << " in instr: " << std::dec << *MI);
103 for (unsigned ii = 0, ee = MI->getNumOperands(); ii != ee; ++ii) {
104 MachineOperand &op = MI->getOperand(ii);
105 if (op.isPCRelativeDisp()) {
106 // the instruction's branch target is made such that it branches to
107 // PC + (branchTarget * 4), so undo that arithmetic here:
108 // Location is the target of the branch
109 // Ref is the location of the instruction, and hence the PC
110 int64_t branchTarget = (Location - (long)Ref) >> 2;
111 MI->SetMachineOperandConst(ii, MachineOperand::MO_SignExtendedImmed,
113 unsigned fixedInstr = SparcV8CodeEmitter::getBinaryCodeForInstr(*MI);
114 MCE.emitWordAt(fixedInstr, Ref);
125 void SparcV8CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
126 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I)
127 emitWord(getBinaryCodeForInstr(*I));
130 int64_t SparcV8CodeEmitter::getMachineOpValue(MachineInstr &MI,
131 MachineOperand &MO) {
132 int64_t rv = 0; // Return value; defaults to 0 for unhandled cases
133 // or things that get fixed up later by the JIT.
134 if (MO.isPCRelativeDisp()) {
135 std::cerr << "SparcV8CodeEmitter: PC-relative disp unhandled\n";
137 } else if (MO.isRegister()) {
139 } else if (MO.isImmediate()) {
140 rv = MO.getImmedValue();
141 } else if (MO.isGlobalAddress()) {
142 GlobalValue *GV = MO.getGlobal();
143 if (MO.isPCRelative()) { // Global variable reference
144 if (void *Addr = (void*)(intptr_t)MCE.getGlobalValueAddress(GV)) {
145 intptr_t CurrPC = MCE.getCurrentPCValue();
146 return (int64_t) (((long)Addr - (long)CurrPC) >> 2);
148 std::cerr << "Unhandled pc-relative global value: " << GV << "\n";
151 } else { // Function reference
152 if (!(rv = (intptr_t)MCE.getGlobalValueAddress(GV))) {
153 if (Function *F = dyn_cast<Function>(GV)) {
154 std::cerr << "SparcV8CodeEmitter error: no lazy fn resolution yet!\n";
157 // Function has not yet been code generated!
158 TheJITResolver->addFunctionReference(MCE.getCurrentPCValue(),
160 // Delayed resolution...
161 return (intptr_t)TheJITResolver->getLazyResolver(cast<Function>(GV));
164 std::cerr << "Unhandled global value: " << GV << "\n";
169 } else if (MO.isMachineBasicBlock()) {
170 const BasicBlock *BB = MO.getMachineBasicBlock()->getBasicBlock();
171 unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
172 BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI)));
173 } else if (MO.isExternalSymbol()) {
174 } else if (MO.isConstantPoolIndex()) {
175 unsigned index = MO.getConstantPoolIndex();
176 rv = MCE.getConstantPoolEntryAddress(index);
177 } else if (MO.isFrameIndex()) {
178 std::cerr << "SparcV8CodeEmitter: error: Frame index unhandled!\n";
181 std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
185 // Adjust for special meaning of operands in some instructions
186 unsigned Opcode = MI.getOpcode();
187 if (Opcode == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) {
189 } else if (Opcode == V8::ORri &&!MO.isRegister() &&!MO.isImmediate()) {
190 rv = (rv >> 10) & 0x03fffff;
196 void *SparcV8JITInfo::getJITStubForFunction(Function *F,
197 MachineCodeEmitter &MCE) {
198 std::cerr << "SparcV8JITInfo::getJITStubForFunction not implemented!\n";
203 void SparcV8JITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
204 std::cerr << "SparcV8JITInfo::replaceMachineCodeForFunction not implemented!";
208 #include "SparcV8GenCodeEmitter.inc"
210 } // end llvm namespace