Added the infrastructute necessary for MIPS JIT support. Patch by Vladimir

Stefanovic. I removed the part that actually emits the instructions cause
I want that to get in better shape first and in incremental steps. This
also makes it easier to review the upcoming parts.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135678 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bruno Cardoso Lopes 2011-07-21 16:28:51 +00:00
parent 4b5e207bf2
commit dca6cdd6a1
12 changed files with 522 additions and 6 deletions

View File

@ -82,7 +82,7 @@ set(LLVM_ALL_TARGETS
)
# List of targets with JIT support:
set(LLVM_TARGETS_WITH_JIT X86 PowerPC ARM)
set(LLVM_TARGETS_WITH_JIT X86 PowerPC ARM Mips)
if( MSVC )
set(LLVM_TARGETS_TO_BUILD X86

View File

@ -484,7 +484,7 @@ else
x86_64) AC_SUBST(TARGET_HAS_JIT,1) ;;
Alpha) AC_SUBST(TARGET_HAS_JIT,0) ;;
ARM) AC_SUBST(TARGET_HAS_JIT,1) ;;
Mips) AC_SUBST(TARGET_HAS_JIT,0) ;;
Mips) AC_SUBST(TARGET_HAS_JIT,1) ;;
XCore) AC_SUBST(TARGET_HAS_JIT,0) ;;
MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;;
SystemZ) AC_SUBST(TARGET_HAS_JIT,0) ;;

2
configure vendored
View File

@ -4865,7 +4865,7 @@ else
;;
ARM) TARGET_HAS_JIT=1
;;
Mips) TARGET_HAS_JIT=0
Mips) TARGET_HAS_JIT=1
;;
XCore) TARGET_HAS_JIT=0
;;

View File

@ -9,6 +9,7 @@ tablegen(MipsGenSubtargetInfo.inc -gen-subtarget)
add_llvm_target(MipsCodeGen
MipsAsmPrinter.cpp
MipsCodeEmitter.cpp
MipsDelaySlotFiller.cpp
MipsEmitGPRestore.cpp
MipsExpandPseudo.cpp

View File

@ -29,6 +29,9 @@ namespace llvm {
FunctionPass *createMipsExpandPseudoPass(MipsTargetMachine &TM);
FunctionPass *createMipsEmitGPRestorePass(MipsTargetMachine &TM);
FunctionPass *createMipsJITCodeEmitterPass(MipsTargetMachine &TM,
JITCodeEmitter &JCE);
} // end namespace llvm;
#endif

View File

@ -0,0 +1,193 @@
//===-- Mips/MipsCodeEmitter.cpp - Convert Mips code to machine code -----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
//
// This file contains the pass that transforms the Mips machine instructions
// into relocatable machine code.
//
//===---------------------------------------------------------------------===//
#define DEBUG_TYPE "jit"
#include "Mips.h"
#include "MipsInstrInfo.h"
#include "MipsRelocations.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/JITCodeEmitter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#ifndef NDEBUG
#include <iomanip>
#endif
#include "llvm/CodeGen/MachineOperand.h"
using namespace llvm;
namespace {
class MipsCodeEmitter : public MachineFunctionPass {
MipsJITInfo *JTI;
const MipsInstrInfo *II;
const TargetData *TD;
const MipsSubtarget *Subtarget;
TargetMachine &TM;
JITCodeEmitter &MCE;
const std::vector<MachineConstantPoolEntry> *MCPEs;
const std::vector<MachineJumpTableEntry> *MJTEs;
bool IsPIC;
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<MachineModuleInfo> ();
MachineFunctionPass::getAnalysisUsage(AU);
}
static char ID;
public:
MipsCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) :
MachineFunctionPass(ID), JTI(0),
II((const MipsInstrInfo *) tm.getInstrInfo()),
TD(tm.getTargetData()), TM(tm), MCE(mce), MCPEs(0), MJTEs(0),
IsPIC(TM.getRelocationModel() == Reloc::PIC_) {
}
bool runOnMachineFunction(MachineFunction &MF);
virtual const char *getPassName() const {
return "Mips Machine Code Emitter";
}
void emitInstruction(const MachineInstr &MI);
unsigned getOperandValue(const MachineOperand &MO,
unsigned relocType = -1);
void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc,
bool MayNeedFarStub = true);
void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc,
intptr_t JTBase = 0);
void emitExternalSymbolAddress(const char *ES, unsigned Reloc);
void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const;
void emitConstPoolAddress(unsigned CPI, unsigned Reloc);
};
}
void MipsCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc,
bool mayNeedFarStub) {
MachineRelocation MR = MachineRelocation::getGV(MCE.getCurrentPCOffset(),
Reloc, const_cast<GlobalValue *> (GV), 0, mayNeedFarStub);
MCE.addRelocation(MR);
}
/// emitMachineBasicBlock - Emit the specified address basic block.
void MipsCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB,
unsigned Reloc, intptr_t JTBase) {
MCE.addRelocation(
MachineRelocation::getBB(MCE.getCurrentPCOffset(), Reloc, BB, JTBase));
}
void MipsCodeEmitter::emitExternalSymbolAddress(const char *ES,
unsigned Reloc) {
MCE.addRelocation(
MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), Reloc, ES, 0, 0,
false));
}
void MipsCodeEmitter::emitJumpTableAddress(unsigned JTIndex, unsigned Reloc)
const {
MCE.addRelocation(
MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), Reloc, JTIndex,
0, false));
}
void MipsCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc) {
MCE.addRelocation(
MachineRelocation::getConstPool
(MCE.getCurrentPCOffset(), Reloc, CPI, 0));
}
/// createMipsJITCodeEmitterPass - Return a pass that emits the collected Mips
/// code to the specified MCE object.
FunctionPass *llvm::createMipsJITCodeEmitterPass(MipsTargetMachine &TM,
JITCodeEmitter &JCE) {
return new MipsCodeEmitter(TM, JCE);
}
char MipsCodeEmitter::ID = 10;
bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
JTI = ((MipsTargetMachine&) MF.getTarget()).getJITInfo();
II = ((const MipsTargetMachine&) MF.getTarget()).getInstrInfo();
TD = ((const MipsTargetMachine&) MF.getTarget()).getTargetData();
Subtarget = &TM.getSubtarget<MipsSubtarget> ();
MCPEs = &MF.getConstantPool()->getConstants();
MJTEs = 0;
if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables();
JTI->Initialize(MF, IsPIC);
MCE.setModuleInfo(&getAnalysis<MachineModuleInfo> ());
do {
DEBUG(errs() << "JITTing function '"
<< MF.getFunction()->getName() << "'\n");
MCE.startFunction(MF);
for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
MBB != E; ++MBB){
MCE.StartMachineBasicBlock(MBB);
for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end();
I != E; ++I)
emitInstruction(*I);
}
} while (MCE.finishFunction(MF));
return false;
}
void MipsCodeEmitter::emitInstruction(const MachineInstr &MI) {}
unsigned MipsCodeEmitter::getOperandValue(const MachineOperand &MO,
unsigned relocType) {
switch (MO.getType()) {
case MachineOperand::MO_Immediate:
return MO.getImm();
case MachineOperand::MO_GlobalAddress:
emitGlobalAddress(MO.getGlobal(), relocType, false);
return 0;
case MachineOperand::MO_ExternalSymbol:
emitExternalSymbolAddress(MO.getSymbolName(), relocType);
return 0;
case MachineOperand::MO_MachineBasicBlock:
emitMachineBasicBlock(MO.getMBB(), relocType, MCE.getCurrentPCValue());
return 0;
case MachineOperand::MO_Register:
return MipsRegisterInfo::getRegisterNumbering(MO.getReg());
case MachineOperand::MO_JumpTableIndex:
emitJumpTableAddress(MO.getIndex(), relocType);
return 0;
case MachineOperand::MO_ConstantPoolIndex:
emitConstPoolAddress(MO.getIndex(), relocType);
return 0;
default: return 0;
}
}

View File

@ -0,0 +1,195 @@
//===- MipsJITInfo.cpp - Implement the JIT interfaces for the Mips target -===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the JIT interfaces for the Mips target.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "jit"
#include "MipsJITInfo.h"
#include "MipsInstrInfo.h"
#include "MipsRelocations.h"
#include "MipsSubtarget.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/JITCodeEmitter.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Memory.h"
#include <cstdlib>
using namespace llvm;
void MipsJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
report_fatal_error("MipsJITInfo::replaceMachineCodeForFunction");
}
/// JITCompilerFunction - This contains the address of the JIT function used to
/// compile a function lazily.
static TargetJITInfo::JITCompilerFn JITCompilerFunction;
// Get the ASMPREFIX for the current host. This is often '_'.
#ifndef __USER_LABEL_PREFIX__
#define __USER_LABEL_PREFIX__
#endif
#define GETASMPREFIX2(X) #X
#define GETASMPREFIX(X) GETASMPREFIX2(X)
#define ASMPREFIX GETASMPREFIX(__USER_LABEL_PREFIX__)
// save registers, call MipsCompilationCallbackC, restore registers
extern "C" {
#if defined (__mips__)
void MipsCompilationCallback();
asm(
".text\n"
".align 2\n"
".globl " ASMPREFIX "MipsCompilationCallback\n"
ASMPREFIX "MipsCompilationCallback:\n"
".ent " ASMPREFIX "MipsCompilationCallback\n"
".set noreorder\n"
".cpload $t9\n"
".frame $29, 32, $31\n"
"addiu $sp, $sp, -40\n"
"sw $a0, 4($sp)\n"
"sw $a1, 8($sp)\n"
"sw $a2, 12($sp)\n"
"sw $a3, 20($sp)\n"
"sw $ra, 24($sp)\n"
"sw $v0, 28($sp)\n"
"sw $v1, 32($sp)\n"
"sw $t8, 36($sp)\n"
".cprestore 16\n"
"addiu $a0, $t8, -16\n"
"jal " ASMPREFIX "MipsCompilationCallbackC\n"
"nop\n"
"lw $a0, 4($sp)\n"
"lw $a1, 8($sp)\n"
"lw $a2, 12($sp)\n"
"lw $a3, 20($sp)\n"
"lw $ra, 24($sp)\n"
"lw $v0, 28($sp)\n"
"lw $v1, 32($sp)\n"
"lw $t8, 36($sp)\n"
"addiu $sp, $sp, 40\n"
"addiu $t8, $t8, -16\n"
"jr $t8\n"
"nop\n"
".set reorder\n"
".end " ASMPREFIX "MipsCompilationCallback\n"
);
#else // host != Mips
void MipsCompilationCallback() {
llvm_unreachable(
"Cannot call MipsCompilationCallback() on a non-Mips arch!");
}
#endif
}
/// MipsCompilationCallbackC - This is the target-specific function invoked
/// by the function stub when we did not know the real target of a call.
/// This function must locate the start of the stub or call site and pass
/// it into the JIT compiler function.
extern "C" void MipsCompilationCallbackC(intptr_t StubAddr) {
// Get the address of the compiled code for this function.
intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr);
*(intptr_t *) (StubAddr) = 2 << 26 | ((NewVal & 0x0fffffff) >> 2); // J NewVal
*(intptr_t *) (StubAddr + 4) = 0; // NOP
*(intptr_t *) (StubAddr + 8) = 0; // NOP
*(intptr_t *) (StubAddr + 12) = 0; // NOP
sys::Memory::InvalidateInstructionCache((void*) StubAddr, 16);
}
TargetJITInfo::LazyResolverFn MipsJITInfo::getLazyResolverFunction(
JITCompilerFn F) {
JITCompilerFunction = F;
return MipsCompilationCallback;
}
TargetJITInfo::StubLayout MipsJITInfo::getStubLayout() {
StubLayout Result = { 24, 4 }; // {Size. Alignment} (of FunctionStub)
return Result;
}
void *MipsJITInfo::emitFunctionStub(const Function* F, void *Fn,
JITCodeEmitter &JCE) {
JCE.emitAlignment(4);
void *Addr = (void*) (JCE.getCurrentPCValue());
unsigned arg0 = ((intptr_t) MipsCompilationCallback >> 16);
if ((((intptr_t) MipsCompilationCallback & 0xffff) >> 15) == 1) {
arg0 += 1; // same hack as in relocate()
}
// LUI t9, %hi(MipsCompilationCallback)
JCE.emitWordLE(0xf << 26 | 25 << 16 | arg0);
// ADDiu t9, t9, %lo(MipsCompilationCallback)
JCE.emitWordLE(9 << 26 | 25 << 21 | 25 << 16
| ((intptr_t) MipsCompilationCallback & 0xffff));
// JALR t8, t9
JCE.emitWordLE(25 << 21 | 24 << 11 | 9);
JCE.emitWordLE(0); // NOP
sys::Memory::InvalidateInstructionCache((void*) Addr, 16);
return Addr;
}
/// relocate - Before the JIT can run a block of code that has been emitted,
/// it must rewrite the code to contain the actual addresses of any
/// referenced global symbols.
void MipsJITInfo::relocate(void *Function, MachineRelocation *MR,
unsigned NumRelocs, unsigned char* GOTBase) {
for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
void *RelocPos = (char*) Function + MR->getMachineCodeOffset();
intptr_t ResultPtr = (intptr_t) MR->getResultPointer();
switch ((Mips::RelocationType) MR->getRelocationType()) {
case Mips::reloc_mips_pcrel:
ResultPtr = (((ResultPtr - (intptr_t) RelocPos) - 4) >> 2) & 0xffff;
*((unsigned*) RelocPos) |= (unsigned) ResultPtr;
break;
case Mips::reloc_mips_j_jal: {
ResultPtr = (ResultPtr & 0x0fffffff) >> 2;
*((unsigned*) RelocPos) |= (unsigned) ResultPtr;
}
break;
case Mips::reloc_mips_hi: {
ResultPtr = ResultPtr >> 16;
// see See MIPS Run Linux, chapter 9.4
if ((((intptr_t) (MR->getResultPointer()) & 0xffff) >> 15) == 1) {
ResultPtr += 1;
}
*((unsigned*) RelocPos) |= (unsigned) ResultPtr;
}
break;
case Mips::reloc_mips_lo:
ResultPtr = ResultPtr & 0xffff;
*((unsigned*) RelocPos) |= (unsigned) ResultPtr;
break;
default:
assert(0 && "MipsJITInfo.unknown relocation;");
}
}
}

View File

@ -0,0 +1,70 @@
//===- MipsJITInfo.h - Mips implementation of the JIT interface -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the MipsJITInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef MIPSJITINFO_H
#define MIPSJITINFO_H
#include "MipsMachineFunction.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/Target/TargetJITInfo.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
namespace llvm {
class MipsTargetMachine;
class MipsJITInfo : public TargetJITInfo {
bool IsPIC;
public:
explicit MipsJITInfo() :
IsPIC(false) {}
/// replaceMachineCodeForFunction - Make it so that calling the function
/// whose machine code is at OLD turns into a call to NEW, perhaps by
/// overwriting OLD with a branch to NEW. This is used for self-modifying
/// code.
///
virtual void replaceMachineCodeForFunction(void *Old, void *New);
// getStubLayout - Returns the size and alignment of the largest call stub
// on Mips.
virtual StubLayout getStubLayout();
/// emitFunctionStub - Use the specified JITCodeEmitter object to emit a
/// small native function that simply calls the function at the specified
/// address.
virtual void *emitFunctionStub(const Function* F, void *Fn,
JITCodeEmitter &JCE);
/// getLazyResolverFunction - Expose the lazy resolver to the JIT.
virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn);
/// relocate - Before the JIT can run a block of code that has been emitted,
/// it must rewrite the code to contain the actual addresses of any
/// referenced global symbols.
virtual void relocate(void *Function, MachineRelocation *MR,
unsigned NumRelocs, unsigned char* GOTBase);
/// Initialize - Initialize internal stage for the function being JITted.
void Initialize(const MachineFunction &MF, bool isPIC) {
IsPIC = isPIC;
}
};
}
#endif

View File

@ -0,0 +1,32 @@
//===- MipsRelocations.h - Mips Code Relocations ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
//
// This file defines the Mips target-specific relocation types
// (for relocation-model=static).
//
//===---------------------------------------------------------------------===//
#ifndef MIPSRELOCATIONS_H_
#define MIPSRELOCATIONS_H_
#include "llvm/CodeGen/MachineRelocation.h"
namespace llvm {
namespace Mips{
enum RelocationType {
reloc_mips_pcrel = 1,
reloc_mips_hi = 3,
reloc_mips_lo = 4,
reloc_mips_j_jal = 5
};
}
}
#endif /* MIPSRELOCATIONS_H_ */

View File

@ -42,7 +42,7 @@ MipsTargetMachine(const Target &T, StringRef TT,
std::string("E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")),
InstrInfo(*this),
FrameLowering(Subtarget),
TLInfo(*this), TSInfo(*this) {
TLInfo(*this), TSInfo(*this), JITInfo() {
}
MipselTargetMachine::
@ -81,3 +81,12 @@ addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) {
PM.add(createMipsExpandPseudoPass(*this));
return true;
}
bool MipsTargetMachine::addCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
JITCodeEmitter &JCE) {
// Machine code emitter pass for Mips.
PM.add(createMipsJITCodeEmitterPass(*this, JCE));
return false;
}

View File

@ -22,6 +22,7 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "MipsJITInfo.h"
namespace llvm {
class formatted_raw_ostream;
@ -33,6 +34,9 @@ namespace llvm {
MipsFrameLowering FrameLowering;
MipsTargetLowering TLInfo;
MipsSelectionDAGInfo TSInfo;
MipsJITInfo JITInfo;
Reloc::Model DefRelocModel; // Reloc model before it's overridden.
public:
MipsTargetMachine(const Target &T, StringRef TT,
StringRef CPU, StringRef FS,
@ -47,6 +51,9 @@ namespace llvm {
{ return &Subtarget; }
virtual const TargetData *getTargetData() const
{ return &DataLayout;}
virtual MipsJITInfo *getJITInfo()
{ return &JITInfo; }
virtual const MipsRegisterInfo *getRegisterInfo() const {
return &InstrInfo.getRegisterInfo();
@ -68,6 +75,10 @@ namespace llvm {
virtual bool addPreRegAlloc(PassManagerBase &PM,
CodeGenOpt::Level OptLevel);
virtual bool addPostRegAlloc(PassManagerBase &, CodeGenOpt::Level);
virtual bool addCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
JITCodeEmitter &JCE);
};
/// MipselTargetMachine - Mipsel target machine.

View File

@ -15,7 +15,9 @@ using namespace llvm;
Target llvm::TheMipsTarget, llvm::TheMipselTarget;
extern "C" void LLVMInitializeMipsTargetInfo() {
RegisterTarget<Triple::mips> X(TheMipsTarget, "mips", "Mips");
RegisterTarget<Triple::mips,
/*HasJIT=*/true> X(TheMipsTarget, "mips", "Mips");
RegisterTarget<Triple::mipsel> Y(TheMipselTarget, "mipsel", "Mipsel");
RegisterTarget<Triple::mipsel,
/*HasJIT=*/true> Y(TheMipselTarget, "mipsel", "Mipsel");
}