From 38aceb871478893bfa87f94c2cb3a344a4c8c2df Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Tue, 8 Oct 2013 07:15:22 +0000 Subject: [PATCH] [Sparc] Implement JIT for SPARC. No new testcases. However, this patch makes all supported JIT testcases in test/ExecutionEngine pass on Sparc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192176 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/CMakeLists.txt | 2 + lib/Target/Sparc/LLVMBuild.txt | 1 + lib/Target/Sparc/Sparc.h | 2 + lib/Target/Sparc/SparcCodeEmitter.cpp | 245 ++++++++++++++++++ lib/Target/Sparc/SparcISelLowering.cpp | 1 + lib/Target/Sparc/SparcInstrInfo.td | 82 +++--- lib/Target/Sparc/SparcJITInfo.cpp | 168 ++++++++++++ lib/Target/Sparc/SparcJITInfo.h | 67 +++++ lib/Target/Sparc/SparcRelocations.h | 41 +++ lib/Target/Sparc/SparcTargetMachine.cpp | 7 + lib/Target/Sparc/SparcTargetMachine.h | 6 + .../Sparc/TargetInfo/SparcTargetInfo.cpp | 8 +- 12 files changed, 586 insertions(+), 44 deletions(-) create mode 100644 lib/Target/Sparc/SparcCodeEmitter.cpp create mode 100644 lib/Target/Sparc/SparcJITInfo.cpp create mode 100644 lib/Target/Sparc/SparcJITInfo.h create mode 100644 lib/Target/Sparc/SparcRelocations.h diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt index 5ac1d3049ae..6339394eab6 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -21,6 +21,8 @@ add_llvm_target(SparcCodeGen SparcSubtarget.cpp SparcTargetMachine.cpp SparcSelectionDAGInfo.cpp + SparcJITInfo.cpp + SparcCodeEmitter.cpp ) add_dependencies(LLVMSparcCodeGen SparcCommonTableGen intrinsics_gen) diff --git a/lib/Target/Sparc/LLVMBuild.txt b/lib/Target/Sparc/LLVMBuild.txt index 7d54d323ac4..fd8e5d9fd8f 100644 --- a/lib/Target/Sparc/LLVMBuild.txt +++ b/lib/Target/Sparc/LLVMBuild.txt @@ -23,6 +23,7 @@ type = TargetGroup name = Sparc parent = Target has_asmprinter = 1 +has_jit = 1 [component_1] type = Library diff --git a/lib/Target/Sparc/Sparc.h b/lib/Target/Sparc/Sparc.h index 98563db4b9e..f2d632e54c0 100644 --- a/lib/Target/Sparc/Sparc.h +++ b/lib/Target/Sparc/Sparc.h @@ -26,6 +26,8 @@ namespace llvm { FunctionPass *createSparcISelDag(SparcTargetMachine &TM); FunctionPass *createSparcDelaySlotFillerPass(TargetMachine &TM); + FunctionPass *createSparcJITCodeEmitterPass(SparcTargetMachine &TM, + JITCodeEmitter &JCE); } // end namespace llvm; diff --git a/lib/Target/Sparc/SparcCodeEmitter.cpp b/lib/Target/Sparc/SparcCodeEmitter.cpp new file mode 100644 index 00000000000..9bfe31fe496 --- /dev/null +++ b/lib/Target/Sparc/SparcCodeEmitter.cpp @@ -0,0 +1,245 @@ +//===-- Sparc/SparcCodeEmitter.cpp - Convert Sparc 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 Sparc machine instructions +// into relocatable machine code. +// +//===---------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "Sparc.h" +#include "MCTargetDesc/SparcBaseInfo.h" +#include "SparcRelocations.h" +#include "SparcTargetMachine.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Support/Debug.h" + +using namespace llvm; + +STATISTIC(NumEmitted, "Number of machine instructions emitted"); + +namespace { + +class SparcCodeEmitter : public MachineFunctionPass { + SparcJITInfo *JTI; + const SparcInstrInfo *II; + const DataLayout *TD; + const SparcSubtarget *Subtarget; + TargetMachine &TM; + JITCodeEmitter &MCE; + const std::vector *MCPEs; + bool IsPIC; + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired (); + MachineFunctionPass::getAnalysisUsage(AU); + } + + static char ID; + +public: + SparcCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) + : MachineFunctionPass(ID), JTI(0), II(0), TD(0), + TM(tm), MCE(mce), MCPEs(0), + IsPIC(TM.getRelocationModel() == Reloc::PIC_) {} + + bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { + return "Sparc Machine Code Emitter"; + } + + /// getBinaryCodeForInstr - This function, generated by the + /// CodeEmitterGenerator using TableGen, produces the binary encoding for + /// machine instructions. + uint64_t getBinaryCodeForInstr(const MachineInstr &MI) const; + + void emitInstruction(MachineBasicBlock::instr_iterator MI, + MachineBasicBlock &MBB); + +private: + /// getMachineOpValue - Return binary encoding of operand. If the machine + /// operand requires relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) const; + + void emitWord(unsigned Word); + + unsigned getRelocation(const MachineInstr &MI, + const MachineOperand &MO) const; + + void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc) const; + void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const; + void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const; + void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc) const; +}; +} // end anonymous namespace. + +char SparcCodeEmitter::ID = 0; + +bool SparcCodeEmitter::runOnMachineFunction(MachineFunction &MF) { + SparcTargetMachine &Target = static_cast( + const_cast(MF.getTarget())); + + JTI = Target.getJITInfo(); + II = Target.getInstrInfo(); + TD = Target.getDataLayout(); + Subtarget = &TM.getSubtarget (); + MCPEs = &MF.getConstantPool()->getConstants(); + JTI->Initialize(MF, IsPIC); + MCE.setModuleInfo(&getAnalysis ()); + + do { + DEBUG(errs() << "JITTing function '" + << MF.getName() << "'\n"); + MCE.startFunction(MF); + + for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); + MBB != E; ++MBB){ + MCE.StartMachineBasicBlock(MBB); + for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(), + E = MBB->instr_end(); I != E;) + emitInstruction(*I++, *MBB); + } + } while (MCE.finishFunction(MF)); + + return false; +} + +void SparcCodeEmitter::emitInstruction(MachineBasicBlock::instr_iterator MI, + MachineBasicBlock &MBB) { + DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << *MI); + + MCE.processDebugLoc(MI->getDebugLoc(), true); + + ++NumEmitted; + + switch (MI->getOpcode()) { + default: { + emitWord(getBinaryCodeForInstr(*MI)); + break; + } + case TargetOpcode::INLINEASM: { + // We allow inline assembler nodes with empty bodies - they can + // implicitly define registers, which is ok for JIT. + if (MI->getOperand(0).getSymbolName()[0]) { + report_fatal_error("JIT does not support inline asm!"); + } + break; + } + case TargetOpcode::PROLOG_LABEL: + case TargetOpcode::EH_LABEL: { + MCE.emitLabel(MI->getOperand(0).getMCSymbol()); + break; + } + case TargetOpcode::IMPLICIT_DEF: + case TargetOpcode::KILL: { + // Do nothing. + break; + } + case SP::GETPCX: { + report_fatal_error("JIT does not support pseudo instruction GETPCX yet!"); + break; + } + } + + MCE.processDebugLoc(MI->getDebugLoc(), false); +} + +void SparcCodeEmitter::emitWord(unsigned Word) { + DEBUG(errs() << " 0x"; + errs().write_hex(Word) << "\n"); + MCE.emitWordBE(Word); +} + +/// getMachineOpValue - Return binary encoding of operand. If the machine +/// operand requires relocation, record the relocation and return zero. +unsigned SparcCodeEmitter::getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) const { + if (MO.isReg()) + return TM.getRegisterInfo()->getEncodingValue(MO.getReg()); + else if (MO.isImm()) + return static_cast(MO.getImm()); + else if (MO.isGlobal()) + emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO)); + else if (MO.isSymbol()) + emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); + else if (MO.isCPI()) + emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO)); + else if (MO.isMBB()) + emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); + else + llvm_unreachable("Unable to encode MachineOperand!"); + return 0; +} +unsigned SparcCodeEmitter::getRelocation(const MachineInstr &MI, + const MachineOperand &MO) const { + + unsigned TF = MO.getTargetFlags(); + switch (TF) { + default: + case SPII::MO_NO_FLAG: break; + case SPII::MO_LO: return SP::reloc_sparc_lo; + case SPII::MO_HI: return SP::reloc_sparc_hi; + case SPII::MO_H44: + case SPII::MO_M44: + case SPII::MO_L44: + case SPII::MO_HH: + case SPII::MO_HM: assert(0 && "FIXME: Implement Medium/Large code model."); + } + + unsigned Opc = MI.getOpcode(); + switch (Opc) { + default: break; + case SP::CALL: return SP::reloc_sparc_pc30; + case SP::BA: + case SP::BCOND: + case SP::FBCOND: return SP::reloc_sparc_pc22; + case SP::BPXCC: return SP::reloc_sparc_pc19; + } + llvm_unreachable("unknown reloc!"); +} + +void SparcCodeEmitter::emitGlobalAddress(const GlobalValue *GV, + unsigned Reloc) const { + MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, + const_cast(GV), 0, + true)); +} + +void SparcCodeEmitter:: +emitExternalSymbolAddress(const char *ES, unsigned Reloc) const { + MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), + Reloc, ES, 0, 0)); +} + +void SparcCodeEmitter:: +emitConstPoolAddress(unsigned CPI, unsigned Reloc) const { + MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), + Reloc, CPI, 0, false)); +} + +void SparcCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB, + unsigned Reloc) const { + MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), + Reloc, BB)); +} + + +/// createSparcJITCodeEmitterPass - Return a pass that emits the collected Sparc +/// code to the specified MCE object. +FunctionPass *llvm::createSparcJITCodeEmitterPass(SparcTargetMachine &TM, + JITCodeEmitter &JCE) { + return new SparcCodeEmitter(TM, JCE); +} + +#include "SparcGenCodeEmitter.inc" diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 8057b39e957..ef215390020 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -1668,6 +1668,7 @@ SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const { switch(getTargetMachine().getCodeModel()) { default: llvm_unreachable("Unsupported absolute code model"); + case CodeModel::JITDefault: case CodeModel::Small: // abs32. return makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG); diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index 9b74147d3e2..b8628b928fa 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -394,63 +394,63 @@ def LDQFri : F3_2<3, 0b100010, // Section B.4 - Store Integer Instructions, p. 95 def STBrr : F3_1<3, 0b000101, - (outs), (ins MEMrr:$addr, IntRegs:$src), - "stb $src, [$addr]", - [(truncstorei8 i32:$src, ADDRrr:$addr)]>; + (outs), (ins MEMrr:$addr, IntRegs:$rd), + "stb $rd, [$addr]", + [(truncstorei8 i32:$rd, ADDRrr:$addr)]>; def STBri : F3_2<3, 0b000101, - (outs), (ins MEMri:$addr, IntRegs:$src), - "stb $src, [$addr]", - [(truncstorei8 i32:$src, ADDRri:$addr)]>; + (outs), (ins MEMri:$addr, IntRegs:$rd), + "stb $rd, [$addr]", + [(truncstorei8 i32:$rd, ADDRri:$addr)]>; def STHrr : F3_1<3, 0b000110, - (outs), (ins MEMrr:$addr, IntRegs:$src), - "sth $src, [$addr]", - [(truncstorei16 i32:$src, ADDRrr:$addr)]>; + (outs), (ins MEMrr:$addr, IntRegs:$rd), + "sth $rd, [$addr]", + [(truncstorei16 i32:$rd, ADDRrr:$addr)]>; def STHri : F3_2<3, 0b000110, - (outs), (ins MEMri:$addr, IntRegs:$src), - "sth $src, [$addr]", - [(truncstorei16 i32:$src, ADDRri:$addr)]>; + (outs), (ins MEMri:$addr, IntRegs:$rd), + "sth $rd, [$addr]", + [(truncstorei16 i32:$rd, ADDRri:$addr)]>; def STrr : F3_1<3, 0b000100, - (outs), (ins MEMrr:$addr, IntRegs:$src), - "st $src, [$addr]", - [(store i32:$src, ADDRrr:$addr)]>; + (outs), (ins MEMrr:$addr, IntRegs:$rd), + "st $rd, [$addr]", + [(store i32:$rd, ADDRrr:$addr)]>; def STri : F3_2<3, 0b000100, - (outs), (ins MEMri:$addr, IntRegs:$src), - "st $src, [$addr]", - [(store i32:$src, ADDRri:$addr)]>; + (outs), (ins MEMri:$addr, IntRegs:$rd), + "st $rd, [$addr]", + [(store i32:$rd, ADDRri:$addr)]>; // Section B.5 - Store Floating-point Instructions, p. 97 def STFrr : F3_1<3, 0b100100, - (outs), (ins MEMrr:$addr, FPRegs:$src), - "st $src, [$addr]", - [(store f32:$src, ADDRrr:$addr)]>; + (outs), (ins MEMrr:$addr, FPRegs:$rd), + "st $rd, [$addr]", + [(store f32:$rd, ADDRrr:$addr)]>; def STFri : F3_2<3, 0b100100, - (outs), (ins MEMri:$addr, FPRegs:$src), - "st $src, [$addr]", - [(store f32:$src, ADDRri:$addr)]>; + (outs), (ins MEMri:$addr, FPRegs:$rd), + "st $rd, [$addr]", + [(store f32:$rd, ADDRri:$addr)]>; def STDFrr : F3_1<3, 0b100111, - (outs), (ins MEMrr:$addr, DFPRegs:$src), - "std $src, [$addr]", - [(store f64:$src, ADDRrr:$addr)]>; + (outs), (ins MEMrr:$addr, DFPRegs:$rd), + "std $rd, [$addr]", + [(store f64:$rd, ADDRrr:$addr)]>; def STDFri : F3_2<3, 0b100111, - (outs), (ins MEMri:$addr, DFPRegs:$src), - "std $src, [$addr]", - [(store f64:$src, ADDRri:$addr)]>; + (outs), (ins MEMri:$addr, DFPRegs:$rd), + "std $rd, [$addr]", + [(store f64:$rd, ADDRri:$addr)]>; def STQFrr : F3_1<3, 0b100110, - (outs), (ins MEMrr:$addr, QFPRegs:$src), - "stq $src, [$addr]", - [(store f128:$src, ADDRrr:$addr)]>, + (outs), (ins MEMrr:$addr, QFPRegs:$rd), + "stq $rd, [$addr]", + [(store f128:$rd, ADDRrr:$addr)]>, Requires<[HasV9, HasHardQuad]>; def STQFri : F3_2<3, 0b100110, - (outs), (ins MEMri:$addr, QFPRegs:$src), - "stq $src, [$addr]", - [(store f128:$src, ADDRri:$addr)]>, + (outs), (ins MEMri:$addr, QFPRegs:$rd), + "stq $rd, [$addr]", + [(store f128:$rd, ADDRri:$addr)]>, Requires<[HasV9, HasHardQuad]>; // Section B.9 - SETHI Instruction, p. 104 def SETHIi: F2_1<0b100, - (outs IntRegs:$dst), (ins i32imm:$src), - "sethi $src, $dst", - [(set i32:$dst, SETHIimm:$src)]>; + (outs IntRegs:$rd), (ins i32imm:$imm22), + "sethi $imm22, $rd", + [(set i32:$rd, SETHIimm:$imm22)]>; // Section B.10 - NOP Instruction, p. 105 // (It's a special case of SETHI) @@ -505,12 +505,12 @@ let Defs = [ICC] in defm ADDCC : F3_12<"addcc", 0b010000, addc>; let Uses = [ICC], Defs = [ICC] in - defm ADDX : F3_12<"addxcc", 0b001000, adde>; + defm ADDX : F3_12<"addxcc", 0b011000, adde>; // Section B.15 - Subtract Instructions, p. 110 defm SUB : F3_12 <"sub" , 0b000100, sub>; let Uses = [ICC], Defs = [ICC] in - defm SUBX : F3_12 <"subxcc" , 0b001100, sube>; + defm SUBX : F3_12 <"subxcc" , 0b011100, sube>; let Defs = [ICC] in defm SUBCC : F3_12 <"subcc", 0b010100, subc>; diff --git a/lib/Target/Sparc/SparcJITInfo.cpp b/lib/Target/Sparc/SparcJITInfo.cpp new file mode 100644 index 00000000000..faeabccc222 --- /dev/null +++ b/lib/Target/Sparc/SparcJITInfo.cpp @@ -0,0 +1,168 @@ +//===-- SparcJITInfo.cpp - Implement the Sparc JIT Interface --------------===// +// +// 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 Sparc target. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "jit" +#include "SparcJITInfo.h" +#include "SparcRelocations.h" + +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/Support/Memory.h" + +using namespace llvm; + +/// JITCompilerFunction - This contains the address of the JIT function used to +/// compile a function lazily. +static TargetJITInfo::JITCompilerFn JITCompilerFunction; + +extern "C" void SparcCompilationCallback(); + +extern "C" { +#if defined (__sparc__) + asm( + ".text\n" + "\t.align 4\n" + "\t.global SparcCompilationCallback\n" + "\t.type SparcCompilationCallback, #function\n" + "SparcCompilationCallback:\n" + // Save current register window. + "\tsave %sp, -192, %sp\n" + // stubaddr+4 is in %g1. + "\tcall SparcCompilationCallbackC\n" + "\t sub %g1, 4, %o0\n" + // restore original register window and + // copy %o0 to %g1 + "\t restore %o0, 0, %g1\n" + // call the new stub + "\tjmp %g1\n" + "\t nop\n" + "\t.size SparcCompilationCallback, .-SparcCompilationCallback" + ); + +#else + void SparcCompilationCallback() { + llvm_unreachable( + "Cannot call SparcCompilationCallback() on a non-sparc arch!"); + } +#endif +} + +#define HI(Val) (((unsigned)(Val)) >> 10) +#define LO(Val) (((unsigned)(Val)) & 0x3FF) + +#define SETHI_INST(imm, rd) (0x01000000 | ((rd) << 25) | ((imm) & 0x3FFFFF)) +#define JMP_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x38 << 19) \ + | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) +#define NOP_INST SETHI_INST(0, 0) + +extern "C" void *SparcCompilationCallbackC(intptr_t StubAddr) { + // Get the address of the compiled code for this function. + intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr); + + // Rewrite the function stub so that we don't end up here every time we + // execute the call. We're replacing the first three instructions of the + // stub with code that jumps to the compiled function: + // sethi %hi(NewVal), %g1 + // jmp %g1+%lo(NewVal) + // nop + + *(intptr_t *)(StubAddr) = SETHI_INST(HI(NewVal), 1); + *(intptr_t *)(StubAddr + 4) = JMP_INST(1, LO(NewVal), 0); + *(intptr_t *)(StubAddr + 8) = NOP_INST; + + sys::Memory::InvalidateInstructionCache((void*) StubAddr, 12); + return (void*)StubAddr; +} + +void SparcJITInfo::replaceMachineCodeForFunction(void *Old, void *New) { + assert(0 && "FIXME: Implement SparcJITInfo::replaceMachineCodeForFunction"); +} + + +TargetJITInfo::StubLayout SparcJITInfo::getStubLayout() { + // The stub contains 3 4-byte instructions, aligned at 4 bytes. See + // emitFunctionStub for details. + + StubLayout Result = { 3*4, 4 }; + return Result; +} + +void *SparcJITInfo::emitFunctionStub(const Function *F, void *Fn, + JITCodeEmitter &JCE) +{ + JCE.emitAlignment(4); + void *Addr = (void*) (JCE.getCurrentPCValue()); + if (!sys::Memory::setRangeWritable(Addr, 12)) + llvm_unreachable("ERROR: Unable to mark stub writable."); + + intptr_t EmittedAddr; + if (Fn != (void*)(intptr_t)SparcCompilationCallback) + EmittedAddr = (intptr_t)Fn; + else + EmittedAddr = (intptr_t)SparcCompilationCallback; + + // sethi %hi(EmittedAddr), %g1 + // jmp %g1+%lo(EmittedAddr), %g1 + // nop + + JCE.emitWordBE(SETHI_INST(HI(EmittedAddr), 1)); + JCE.emitWordBE(JMP_INST(1, LO(EmittedAddr), 1)); + JCE.emitWordBE(NOP_INST); + + sys::Memory::InvalidateInstructionCache(Addr, 12); + if (!sys::Memory::setRangeExecutable(Addr, 12)) + llvm_unreachable("ERROR: Unable to mark stub executable."); + + return Addr; +} + +TargetJITInfo::LazyResolverFn +SparcJITInfo::getLazyResolverFunction(JITCompilerFn F) { + JITCompilerFunction = F; + return SparcCompilationCallback; +} + +/// 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 SparcJITInfo::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 ((SP::RelocationType) MR->getRelocationType()) { + default: llvm_unreachable("Unknown reloc!"); + case SP::reloc_sparc_hi: + ResultPtr = (ResultPtr >> 10) & 0x3fffff; + break; + + case SP::reloc_sparc_lo: + ResultPtr = (ResultPtr & 0x3ff); + break; + + case SP::reloc_sparc_pc30: + ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x3fffffff; + break; + + case SP::reloc_sparc_pc22: + ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x3fffff; + break; + + case SP::reloc_sparc_pc19: + ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x7ffff; + break; + } + *((unsigned*) RelocPos) |= (unsigned) ResultPtr; + } +} + + diff --git a/lib/Target/Sparc/SparcJITInfo.h b/lib/Target/Sparc/SparcJITInfo.h new file mode 100644 index 00000000000..9c6e488e488 --- /dev/null +++ b/lib/Target/Sparc/SparcJITInfo.h @@ -0,0 +1,67 @@ +//==- SparcJITInfo.h - Sparc 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 SparcJITInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef SPARCJITINFO_H +#define SPARCJITINFO_H + +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Target/TargetJITInfo.h" + +namespace llvm { +class SparcTargetMachine; + +class SparcJITInfo : public TargetJITInfo { + + bool IsPIC; + + public: + explicit SparcJITInfo() + : 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 Sparc. + 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 diff --git a/lib/Target/Sparc/SparcRelocations.h b/lib/Target/Sparc/SparcRelocations.h new file mode 100644 index 00000000000..388cfe75a5e --- /dev/null +++ b/lib/Target/Sparc/SparcRelocations.h @@ -0,0 +1,41 @@ +//===-- SparcRelocations.h - Sparc 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 Sparc target-specific relocation types +// (for relocation-model=static). +// +//===----------------------------------------------------------------------===// + +#ifndef SPARC_RELOCATIONS_H +#define SPARC_RELOCATIONS_H + +#include "llvm/CodeGen/MachineRelocation.h" + +namespace llvm { + namespace SP { + enum RelocationType { + // reloc_sparc_hi - upper 22 bits + reloc_sparc_hi = 1, + + // reloc_sparc_lo - lower 10 bits + reloc_sparc_lo = 2, + + // reloc_sparc_pc30 - pc rel. 30 bits for call + reloc_sparc_pc30 = 3, + + // reloc_sparc_pc22 - pc rel. 22 bits for branch + reloc_sparc_pc22 = 4, + + // reloc_sparc_pc22 - pc rel. 19 bits for branch with icc/xcc + reloc_sparc_pc19 = 5 + }; + } +} + +#endif diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp index a7355f49fae..0f936747cfe 100644 --- a/lib/Target/Sparc/SparcTargetMachine.cpp +++ b/lib/Target/Sparc/SparcTargetMachine.cpp @@ -65,6 +65,13 @@ bool SparcPassConfig::addInstSelector() { return false; } +bool SparcTargetMachine::addCodeEmitter(PassManagerBase &PM, + JITCodeEmitter &JCE) { + // Machine code emitter pass for Sparc. + PM.add(createSparcJITCodeEmitterPass(*this, JCE)); + return false; +} + /// addPreEmitPass - This pass may be implemented by targets that want to run /// passes immediately before machine code is emitted. This should return /// true if -print-machineinstrs should print out the code after the passes. diff --git a/lib/Target/Sparc/SparcTargetMachine.h b/lib/Target/Sparc/SparcTargetMachine.h index 081075de2dc..8c9bcd36bf3 100644 --- a/lib/Target/Sparc/SparcTargetMachine.h +++ b/lib/Target/Sparc/SparcTargetMachine.h @@ -17,6 +17,7 @@ #include "SparcFrameLowering.h" #include "SparcISelLowering.h" #include "SparcInstrInfo.h" +#include "SparcJITInfo.h" #include "SparcSelectionDAGInfo.h" #include "SparcSubtarget.h" #include "llvm/IR/DataLayout.h" @@ -32,6 +33,7 @@ class SparcTargetMachine : public LLVMTargetMachine { SparcTargetLowering TLInfo; SparcSelectionDAGInfo TSInfo; SparcFrameLowering FrameLowering; + SparcJITInfo JITInfo; public: SparcTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, @@ -52,10 +54,14 @@ public: virtual const SparcSelectionDAGInfo* getSelectionDAGInfo() const { return &TSInfo; } + virtual SparcJITInfo *getJITInfo() { + return &JITInfo; + } virtual const DataLayout *getDataLayout() const { return &DL; } // Pass Pipeline Configuration virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); + virtual bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE); }; /// SparcV8TargetMachine - Sparc 32-bit target machine diff --git a/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp b/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp index bb714632349..4eea16370ea 100644 --- a/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp +++ b/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp @@ -15,7 +15,9 @@ using namespace llvm; Target llvm::TheSparcTarget; Target llvm::TheSparcV9Target; -extern "C" void LLVMInitializeSparcTargetInfo() { - RegisterTarget X(TheSparcTarget, "sparc", "Sparc"); - RegisterTarget Y(TheSparcV9Target, "sparcv9", "Sparc V9"); +extern "C" void LLVMInitializeSparcTargetInfo() { + RegisterTarget + X(TheSparcTarget, "sparc", "Sparc"); + RegisterTarget + Y(TheSparcV9Target, "sparcv9", "Sparc V9"); } -- 2.34.1