mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
[SystemZ] Add MCJIT support
Another step towards reinstating the SystemZ backend. I'll commit the configure changes separately (TARGET_HAS_JIT etc.), then commit a patch to enable the MCJIT tests on SystemZ. llvm-svn: 181015
This commit is contained in:
parent
a62683d68c
commit
2ad4879885
@ -234,6 +234,12 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
||||
Check(Section.isReadOnlyData(IsReadOnly));
|
||||
Check(Section.getSize(DataSize));
|
||||
Check(Section.getName(Name));
|
||||
if (StubSize > 0) {
|
||||
unsigned StubAlignment = getStubAlignment();
|
||||
unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
|
||||
if (StubAlignment > EndAlignment)
|
||||
StubBufSize += StubAlignment - EndAlignment;
|
||||
}
|
||||
|
||||
unsigned Allocate;
|
||||
unsigned SectionID = Sections.size();
|
||||
@ -370,6 +376,13 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
|
||||
writeInt32BE(Addr+36, 0xE96C0010); // ld r11, 16(r2)
|
||||
writeInt32BE(Addr+40, 0x4E800420); // bctr
|
||||
|
||||
return Addr;
|
||||
} else if (Arch == Triple::systemz) {
|
||||
writeInt16BE(Addr, 0xC418); // lgrl %r1,.+8
|
||||
writeInt16BE(Addr+2, 0x0000);
|
||||
writeInt16BE(Addr+4, 0x0004);
|
||||
writeInt16BE(Addr+6, 0x07F1); // brc 15,%r1
|
||||
// 8-byte address stored at Addr + 8
|
||||
return Addr;
|
||||
}
|
||||
return Addr;
|
||||
|
@ -560,6 +560,42 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section,
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend) {
|
||||
uint8_t *LocalAddress = Section.Address + Offset;
|
||||
switch (Type) {
|
||||
default:
|
||||
llvm_unreachable("Relocation type not implemented yet!");
|
||||
break;
|
||||
case ELF::R_390_PC16DBL:
|
||||
case ELF::R_390_PLT16DBL: {
|
||||
int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
|
||||
assert(int16_t(Delta / 2) * 2 == Delta && "R_390_PC16DBL overflow");
|
||||
writeInt16BE(LocalAddress, Delta / 2);
|
||||
break;
|
||||
}
|
||||
case ELF::R_390_PC32DBL:
|
||||
case ELF::R_390_PLT32DBL: {
|
||||
int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
|
||||
assert(int32_t(Delta / 2) * 2 == Delta && "R_390_PC32DBL overflow");
|
||||
writeInt32BE(LocalAddress, Delta / 2);
|
||||
break;
|
||||
}
|
||||
case ELF::R_390_PC32: {
|
||||
int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
|
||||
assert(int32_t(Delta) == Delta && "R_390_PC32 overflow");
|
||||
writeInt32BE(LocalAddress, Delta);
|
||||
break;
|
||||
}
|
||||
case ELF::R_390_64:
|
||||
writeInt64BE(LocalAddress, Value + Addend);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE,
|
||||
uint64_t Value) {
|
||||
const SectionEntry &Section = Sections[RE.SectionID];
|
||||
@ -595,6 +631,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
|
||||
case Triple::ppc64:
|
||||
resolvePPC64Relocation(Section, Offset, Value, Type, Addend);
|
||||
break;
|
||||
case Triple::systemz:
|
||||
resolveSystemZRelocation(Section, Offset, Value, Type, Addend);
|
||||
break;
|
||||
default: llvm_unreachable("Unsupported CPU type!");
|
||||
}
|
||||
}
|
||||
@ -839,6 +878,53 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
|
||||
else
|
||||
addRelocationForSection(RE, Value.SectionID);
|
||||
}
|
||||
} else if (Arch == Triple::systemz &&
|
||||
(RelType == ELF::R_390_PLT32DBL ||
|
||||
RelType == ELF::R_390_GOTENT)) {
|
||||
// Create function stubs for both PLT and GOT references, regardless of
|
||||
// whether the GOT reference is to data or code. The stub contains the
|
||||
// full address of the symbol, as needed by GOT references, and the
|
||||
// executable part only adds an overhead of 8 bytes.
|
||||
//
|
||||
// We could try to conserve space by allocating the code and data
|
||||
// parts of the stub separately. However, as things stand, we allocate
|
||||
// a stub for every relocation, so using a GOT in JIT code should be
|
||||
// no less space efficient than using an explicit constant pool.
|
||||
DEBUG(dbgs() << "\t\tThis is a SystemZ indirect relocation.");
|
||||
SectionEntry &Section = Sections[SectionID];
|
||||
|
||||
// Look for an existing stub.
|
||||
StubMap::const_iterator i = Stubs.find(Value);
|
||||
uintptr_t StubAddress;
|
||||
if (i != Stubs.end()) {
|
||||
StubAddress = uintptr_t(Section.Address) + i->second;
|
||||
DEBUG(dbgs() << " Stub function found\n");
|
||||
} else {
|
||||
// Create a new stub function.
|
||||
DEBUG(dbgs() << " Create a new stub function\n");
|
||||
|
||||
uintptr_t BaseAddress = uintptr_t(Section.Address);
|
||||
uintptr_t StubAlignment = getStubAlignment();
|
||||
StubAddress = (BaseAddress + Section.StubOffset +
|
||||
StubAlignment - 1) & -StubAlignment;
|
||||
unsigned StubOffset = StubAddress - BaseAddress;
|
||||
|
||||
Stubs[Value] = StubOffset;
|
||||
createStubFunction((uint8_t *)StubAddress);
|
||||
RelocationEntry RE(SectionID, StubOffset + 8,
|
||||
ELF::R_390_64, Value.Addend - Addend);
|
||||
if (Value.SymbolName)
|
||||
addRelocationForSymbol(RE, Value.SymbolName);
|
||||
else
|
||||
addRelocationForSection(RE, Value.SectionID);
|
||||
Section.StubOffset = StubOffset + getMaxStubSize();
|
||||
}
|
||||
|
||||
if (RelType == ELF::R_390_GOTENT)
|
||||
resolveRelocation(Section, Offset, StubAddress + 8,
|
||||
ELF::R_390_PC32DBL, Addend);
|
||||
else
|
||||
resolveRelocation(Section, Offset, StubAddress, RelType, Addend);
|
||||
} else {
|
||||
RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
|
||||
if (Value.SymbolName)
|
||||
|
@ -67,6 +67,11 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||
uint32_t Type,
|
||||
int64_t Addend);
|
||||
|
||||
void resolveSystemZRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend);
|
||||
|
||||
uint64_t findPPC64TOC() const;
|
||||
void findOPDEntrySection(ObjectImage &Obj,
|
||||
|
@ -172,10 +172,19 @@ protected:
|
||||
return 16;
|
||||
else if (Arch == Triple::ppc64)
|
||||
return 44;
|
||||
else if (Arch == Triple::systemz)
|
||||
return 16;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline unsigned getStubAlignment() {
|
||||
if (Arch == Triple::systemz)
|
||||
return 8;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool HasError;
|
||||
std::string ErrorStr;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user