Correct MCJIT functionality for MIPS32 architecture.

No new tests are added.
All tests in ExecutionEngine/MCJIT that have been failing pass after this patch
is applied (when "make check" is done on a mips board). 

Patch by Petar Jovanovic.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162135 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Akira Hatanaka 2012-08-17 21:28:04 +00:00
parent a67eda76c0
commit b889e0cd2f
9 changed files with 137 additions and 8 deletions

View File

@ -2044,6 +2044,9 @@ unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const {
return Triple::arm;
case ELF::EM_HEXAGON:
return Triple::hexagon;
case ELF::EM_MIPS:
return (target_endianness == support::little) ?
Triple::mipsel : Triple::mips;
default:
return Triple::UnknownArch;
}

View File

@ -108,7 +108,8 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
CommonSymbols[*i] = Size;
} else {
if (SymType == object::SymbolRef::ST_Function ||
SymType == object::SymbolRef::ST_Data) {
SymType == object::SymbolRef::ST_Data ||
SymType == object::SymbolRef::ST_Unknown) {
uint64_t FileOffset;
StringRef SectionData;
section_iterator si = obj->end_sections();
@ -333,15 +334,31 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE,
}
uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
// TODO: There is only ARM far stub now. We should add the Thumb stub,
// and stubs for branches Thumb - ARM and ARM - Thumb.
if (Arch == Triple::arm) {
// TODO: There is only ARM far stub now. We should add the Thumb stub,
// and stubs for branches Thumb - ARM and ARM - Thumb.
uint32_t *StubAddr = (uint32_t*)Addr;
*StubAddr = 0xe51ff004; // ldr pc,<label>
return (uint8_t*)++StubAddr;
}
else
} else if (Arch == Triple::mipsel) {
uint32_t *StubAddr = (uint32_t*)Addr;
// 0: 3c190000 lui t9,%hi(addr).
// 4: 27390000 addiu t9,t9,%lo(addr).
// 8: 03200008 jr t9.
// c: 00000000 nop.
const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000;
const unsigned JrT9Instr = 0x03200008, NopInstr = 0x0;
*StubAddr = LuiT9Instr;
StubAddr++;
*StubAddr = AdduiT9Instr;
StubAddr++;
*StubAddr = JrT9Instr;
StubAddr++;
*StubAddr = NopInstr;
return Addr;
}
return Addr;
}
// Assign an address to a symbol name and resolve all the relocations

View File

@ -306,6 +306,44 @@ void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress,
}
}
void RuntimeDyldELF::resolveMIPSRelocation(uint8_t *LocalAddress,
uint32_t FinalAddress,
uint32_t Value,
uint32_t Type,
int32_t Addend) {
uint32_t* TargetPtr = (uint32_t*)LocalAddress;
Value += Addend;
DEBUG(dbgs() << "resolveMipselocation, LocalAddress: " << LocalAddress
<< " FinalAddress: " << format("%p",FinalAddress)
<< " Value: " << format("%x",Value)
<< " Type: " << format("%x",Type)
<< " Addend: " << format("%x",Addend)
<< "\n");
switch(Type) {
default:
llvm_unreachable("Not implemented relocation type!");
break;
case ELF::R_MIPS_32:
*TargetPtr = Value + (*TargetPtr);
break;
case ELF::R_MIPS_26:
*TargetPtr = ((*TargetPtr) & 0xfc000000) | (( Value & 0x0fffffff) >> 2);
break;
case ELF::R_MIPS_HI16:
// Get the higher 16-bits. Also add 1 if bit 15 is 1.
Value += ((*TargetPtr) & 0x0000ffff) << 16;
*TargetPtr = ((*TargetPtr) & 0xffff0000) |
(((Value + 0x8000) >> 16) & 0xffff);
break;
case ELF::R_MIPS_LO16:
Value += ((*TargetPtr) & 0x0000ffff);
*TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff);
break;
}
}
void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress,
uint64_t FinalAddress,
uint64_t Value,
@ -326,6 +364,12 @@ void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress,
(uint32_t)(Value & 0xffffffffL), Type,
(uint32_t)(Addend & 0xffffffffL));
break;
case Triple::mips: // Fall through.
case Triple::mipsel:
resolveMIPSRelocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
(uint32_t)(Value & 0xffffffffL), Type,
(uint32_t)(Addend & 0xffffffffL));
break;
default: llvm_unreachable("Unsupported CPU type!");
}
}
@ -423,6 +467,53 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
Section.StubOffset, RelType, 0);
Section.StubOffset += getMaxStubSize();
}
} else if (Arch == Triple::mipsel && RelType == ELF::R_MIPS_26) {
// This is an Mips branch relocation, need to use a stub function.
DEBUG(dbgs() << "\t\tThis is a Mips branch relocation.");
SectionEntry &Section = Sections[Rel.SectionID];
uint8_t *Target = Section.Address + Rel.Offset;
uint32_t *TargetAddress = (uint32_t *)Target;
// Extract the addend from the instruction.
uint32_t Addend = ((*TargetAddress) & 0x03ffffff) << 2;
Value.Addend += Addend;
// Look up for existing stub.
StubMap::const_iterator i = Stubs.find(Value);
if (i != Stubs.end()) {
resolveRelocation(Target, (uint64_t)Target,
(uint64_t)Section.Address +
i->second, RelType, 0);
DEBUG(dbgs() << " Stub function found\n");
} else {
// Create a new stub function.
DEBUG(dbgs() << " Create a new stub function\n");
Stubs[Value] = Section.StubOffset;
uint8_t *StubTargetAddr = createStubFunction(Section.Address +
Section.StubOffset);
// Creating Hi and Lo relocations for the filled stub instructions.
RelocationEntry REHi(Rel.SectionID,
StubTargetAddr - Section.Address,
ELF::R_MIPS_HI16, Value.Addend);
RelocationEntry RELo(Rel.SectionID,
StubTargetAddr - Section.Address + 4,
ELF::R_MIPS_LO16, Value.Addend);
if (Value.SymbolName) {
addRelocationForSymbol(REHi, Value.SymbolName);
addRelocationForSymbol(RELo, Value.SymbolName);
} else {
addRelocationForSection(REHi, Value.SectionID);
addRelocationForSection(RELo, Value.SectionID);
}
resolveRelocation(Target, (uint64_t)Target,
(uint64_t)Section.Address +
Section.StubOffset, RelType, 0);
Section.StubOffset += getMaxStubSize();
}
} else {
RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend);
if (Value.SymbolName)

View File

@ -42,6 +42,12 @@ protected:
uint32_t Type,
int32_t Addend);
void resolveMIPSRelocation(uint8_t *LocalAddress,
uint32_t FinalAddress,
uint32_t Value,
uint32_t Type,
int32_t Addend);
virtual void resolveRelocation(uint8_t *LocalAddress,
uint64_t FinalAddress,
uint64_t Value,

View File

@ -161,6 +161,8 @@ protected:
inline unsigned getMaxStubSize() {
if (Arch == Triple::arm || Arch == Triple::thumb)
return 8; // 32-bit instruction and 32-bit address
else if (Arch == Triple::mipsel)
return 16;
else
return 0;
}

View File

@ -21,6 +21,7 @@ add_llvm_target(MipsCodeGen
MipsAsmPrinter.cpp
MipsCodeEmitter.cpp
MipsDelaySlotFiller.cpp
MipsELFWriterInfo.cpp
MipsJITInfo.cpp
MipsInstrInfo.cpp
MipsISelDAGToDAG.cpp

View File

@ -34,7 +34,8 @@ namespace {
class MipsELFObjectWriter : public MCELFObjectTargetWriter {
public:
MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64);
MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
bool _isN64, bool IsLittleEndian);
virtual ~MipsELFObjectWriter();
@ -53,7 +54,7 @@ namespace {
}
MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
bool _isN64)
bool _isN64, bool IsLittleEndian)
: MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS,
/*HasRelocationAddend*/ false,
/*IsN64*/ _isN64) {}
@ -274,6 +275,7 @@ MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS,
bool IsLittleEndian,
bool Is64Bit) {
MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI,
(Is64Bit) ? true : false);
(Is64Bit) ? true : false,
IsLittleEndian);
return createELFObjectWriter(MOTW, OS, IsLittleEndian);
}

View File

@ -43,6 +43,7 @@ MipsTargetMachine(const Target &T, StringRef TT,
bool isLittle)
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
Subtarget(TT, CPU, FS, isLittle),
ELFWriterInfo(false, isLittle),
DataLayout(isLittle ?
(Subtarget.isABI_N64() ?
"e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-n32" :

View File

@ -20,6 +20,7 @@
#include "MipsJITInfo.h"
#include "MipsSelectionDAGInfo.h"
#include "MipsSubtarget.h"
#include "MipsELFWriterInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameLowering.h"
@ -36,6 +37,7 @@ class MipsTargetMachine : public LLVMTargetMachine {
MipsTargetLowering TLInfo;
MipsSelectionDAGInfo TSInfo;
MipsJITInfo JITInfo;
MipsELFWriterInfo ELFWriterInfo;
public:
MipsTargetMachine(const Target &T, StringRef TT,
@ -69,6 +71,10 @@ public:
return &TSInfo;
}
virtual const MipsELFWriterInfo *getELFWriterInfo() const {
return &ELFWriterInfo;
}
// Pass Pipeline Configuration
virtual TargetPassConfig *createPassConfig(PassManagerBase &PM);
virtual bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE);