mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-13 23:18:58 +00:00
Factor some code out and support for Jump Table relocations
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74760 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2373c99433
commit
0b1308f189
@ -97,6 +97,9 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
||||
// Emit constant pool to appropriate section(s)
|
||||
emitConstantPool(MF.getConstantPool());
|
||||
|
||||
// Emit jump tables to appropriate section
|
||||
emitJumpTables(MF.getJumpTableInfo());
|
||||
|
||||
// Relocations
|
||||
// -----------
|
||||
// If we have emitted any relocations to function-specific objects such as
|
||||
@ -116,13 +119,22 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
||||
Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex());
|
||||
MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]);
|
||||
MR.setResultPointer((void*)Addr);
|
||||
} else if (MR.isJumpTableIndex()) {
|
||||
Addr = getJumpTableEntryAddress(MR.getJumpTableIndex());
|
||||
MR.setResultPointer((void*)Addr);
|
||||
MR.setConstantVal(JumpTableSectionIdx);
|
||||
} else {
|
||||
assert(0 && "Unhandled relocation type");
|
||||
}
|
||||
ES->addRelocation(MR);
|
||||
}
|
||||
Relocations.clear();
|
||||
|
||||
// Clear per-function data structures.
|
||||
Relocations.clear();
|
||||
CPLocations.clear();
|
||||
CPSections.clear();
|
||||
JTLocations.clear();
|
||||
MBBLocations.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -158,4 +170,56 @@ void ELFCodeEmitter::emitConstantPool(MachineConstantPool *MCP) {
|
||||
}
|
||||
}
|
||||
|
||||
/// emitJumpTables - Emit all the jump tables for a given jump table info
|
||||
/// record to the appropriate section.
|
||||
void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) {
|
||||
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
|
||||
if (JT.empty()) return;
|
||||
|
||||
// FIXME: handle PIC codegen
|
||||
assert(TM.getRelocationModel() != Reloc::PIC_ &&
|
||||
"PIC codegen not yet handled for elf jump tables!");
|
||||
|
||||
const TargetAsmInfo *TAI = TM.getTargetAsmInfo();
|
||||
|
||||
// Get the ELF Section to emit the jump table
|
||||
unsigned Align = TM.getTargetData()->getPointerABIAlignment();
|
||||
std::string JTName(TAI->getJumpTableDataSection());
|
||||
ELFSection &JTSection = EW.getJumpTableSection(JTName, Align);
|
||||
JumpTableSectionIdx = JTSection.SectionIdx;
|
||||
|
||||
// Entries in the JT Section are relocated against the text section
|
||||
ELFSection &TextSection = EW.getTextSection();
|
||||
|
||||
// For each JT, record its offset from the start of the section
|
||||
for (unsigned i = 0, e = JT.size(); i != e; ++i) {
|
||||
const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs;
|
||||
|
||||
DOUT << "JTSection.size(): " << JTSection.size() << "\n";
|
||||
DOUT << "JTLocations.size: " << JTLocations.size() << "\n";
|
||||
|
||||
// Record JT 'i' offset in the JT section
|
||||
JTLocations.push_back(JTSection.size());
|
||||
|
||||
// Each MBB entry in the Jump table section has a relocation entry
|
||||
// against the current text section.
|
||||
for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) {
|
||||
MachineRelocation MR =
|
||||
MachineRelocation::getBB(JTSection.size(),
|
||||
MachineRelocation::VANILLA,
|
||||
MBBs[mi]);
|
||||
|
||||
// Offset of JT 'i' in JT section
|
||||
MR.setResultPointer((void*)getMachineBasicBlockAddress(MBBs[mi]));
|
||||
MR.setConstantVal(TextSection.SectionIdx);
|
||||
|
||||
// Add the relocation to the Jump Table section
|
||||
JTSection.addRelocation(MR);
|
||||
|
||||
// Output placeholder for MBB in the JT section
|
||||
JTSection.emitWord(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -40,6 +40,10 @@ namespace llvm {
|
||||
/// containing the constant pool entry for that index.
|
||||
std::vector<unsigned> CPSections;
|
||||
|
||||
/// JTLocations - This is a map of jump table indices to offsets from the
|
||||
/// start of the section for that jump table index.
|
||||
std::vector<uintptr_t> JTLocations;
|
||||
|
||||
/// MBBLocations - This vector is a mapping from MBB ID's to their address.
|
||||
/// It is filled in by the StartMachineBasicBlock callback and queried by
|
||||
/// the getMachineBasicBlockAddress callback.
|
||||
@ -48,8 +52,12 @@ namespace llvm {
|
||||
/// FnStartPtr - Pointer to the start location of the current function
|
||||
/// in the buffer
|
||||
uint8_t *FnStartPtr;
|
||||
|
||||
/// JumpTableSectionIdx - Holds the index of the Jump Table Section
|
||||
unsigned JumpTableSectionIdx;
|
||||
public:
|
||||
explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {}
|
||||
explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM),
|
||||
JumpTableSectionIdx(0) {}
|
||||
|
||||
void startFunction(MachineFunction &F);
|
||||
bool finishFunction(MachineFunction &F);
|
||||
@ -64,25 +72,20 @@ namespace llvm {
|
||||
MBBLocations[MBB->getNumber()] = getCurrentPCOffset();
|
||||
}
|
||||
|
||||
virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) {
|
||||
assert(MBBLocations.size() > (unsigned)MBB->getNumber() &&
|
||||
MBBLocations[MBB->getNumber()] && "MBB not emitted!");
|
||||
return MBBLocations[MBB->getNumber()];
|
||||
}
|
||||
|
||||
virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
|
||||
assert(CPLocations.size() > Index && "CP not emitted!");
|
||||
return CPLocations[Index];
|
||||
}
|
||||
|
||||
virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const {
|
||||
assert(0 && "JT not implementated yet!");
|
||||
return 0;
|
||||
assert(JTLocations.size() > Index && "JT not emitted!");
|
||||
return JTLocations[Index];
|
||||
}
|
||||
|
||||
virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const {
|
||||
assert(0 && "JT not implementated yet!");
|
||||
return 0;
|
||||
assert(MBBLocations.size() > (unsigned)MBB->getNumber() &&
|
||||
MBBLocations[MBB->getNumber()] && "MBB not emitted!");
|
||||
return MBBLocations[MBB->getNumber()];
|
||||
}
|
||||
|
||||
virtual uintptr_t getLabelAddress(uint64_t Label) const {
|
||||
@ -100,7 +103,11 @@ namespace llvm {
|
||||
/// the constant should live in and emit the constant.
|
||||
void emitConstantPool(MachineConstantPool *MCP);
|
||||
|
||||
virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { }
|
||||
/// emitJumpTables - Emit all the jump tables for a given jump table info
|
||||
/// record to the appropriate section.
|
||||
void emitJumpTables(MachineJumpTableInfo *MJTI);
|
||||
|
||||
virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) {}
|
||||
|
||||
/// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE!
|
||||
void startGVStub(const GlobalValue* F, unsigned StubSize,
|
||||
|
@ -166,43 +166,51 @@ unsigned ELFWriter::getGlobalELFLinkage(const GlobalValue *GV) {
|
||||
return ELFSym::STB_GLOBAL;
|
||||
}
|
||||
|
||||
// getElfSectionFlags - Get the ELF Section Header based on the
|
||||
// flags defined in ELFTargetAsmInfo.
|
||||
unsigned ELFWriter::getElfSectionFlags(unsigned Flags) {
|
||||
unsigned ElfSectionFlags = ELFSection::SHF_ALLOC;
|
||||
|
||||
if (Flags & SectionFlags::Code)
|
||||
ElfSectionFlags |= ELFSection::SHF_EXECINSTR;
|
||||
if (Flags & SectionFlags::Writeable)
|
||||
ElfSectionFlags |= ELFSection::SHF_WRITE;
|
||||
if (Flags & SectionFlags::Mergeable)
|
||||
ElfSectionFlags |= ELFSection::SHF_MERGE;
|
||||
if (Flags & SectionFlags::TLS)
|
||||
ElfSectionFlags |= ELFSection::SHF_TLS;
|
||||
if (Flags & SectionFlags::Strings)
|
||||
ElfSectionFlags |= ELFSection::SHF_STRINGS;
|
||||
|
||||
return ElfSectionFlags;
|
||||
}
|
||||
|
||||
// For global symbols without a section, return the Null section as a
|
||||
// placeholder
|
||||
ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
|
||||
ELFSym &Sym) {
|
||||
const Section *S = TAI->SectionForGlobal(GV);
|
||||
unsigned Flags = S->getFlags();
|
||||
unsigned SectionType = ELFSection::SHT_PROGBITS;
|
||||
unsigned SHdrFlags = ELFSection::SHF_ALLOC;
|
||||
DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n";
|
||||
|
||||
// If this is an external global, the symbol does not have a section.
|
||||
// If this is a declaration, the symbol does not have a section.
|
||||
if (!GV->hasInitializer()) {
|
||||
Sym.SectionIdx = ELFSection::SHN_UNDEF;
|
||||
return getNullSection();
|
||||
}
|
||||
|
||||
// Get the name and flags of the section for the global
|
||||
const Section *S = TAI->SectionForGlobal(GV);
|
||||
unsigned SectionType = ELFSection::SHT_PROGBITS;
|
||||
unsigned SectionFlags = getElfSectionFlags(S->getFlags());
|
||||
DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n";
|
||||
|
||||
const TargetData *TD = TM.getTargetData();
|
||||
unsigned Align = TD->getPreferredAlignment(GV);
|
||||
Constant *CV = GV->getInitializer();
|
||||
|
||||
if (Flags & SectionFlags::Code)
|
||||
SHdrFlags |= ELFSection::SHF_EXECINSTR;
|
||||
if (Flags & SectionFlags::Writeable)
|
||||
SHdrFlags |= ELFSection::SHF_WRITE;
|
||||
if (Flags & SectionFlags::Mergeable)
|
||||
SHdrFlags |= ELFSection::SHF_MERGE;
|
||||
if (Flags & SectionFlags::TLS)
|
||||
SHdrFlags |= ELFSection::SHF_TLS;
|
||||
if (Flags & SectionFlags::Strings)
|
||||
SHdrFlags |= ELFSection::SHF_STRINGS;
|
||||
|
||||
// If this global has a zero initializer, go to .bss or common section.
|
||||
// Variables are part of the common block if they are zero initialized
|
||||
// and allowed to be merged with other symbols.
|
||||
if (CV->isNullValue() || isa<UndefValue>(CV)) {
|
||||
SectionType = ELFSection::SHT_NOBITS;
|
||||
ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags);
|
||||
ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags);
|
||||
if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
|
||||
GV->hasCommonLinkage()) {
|
||||
Sym.SectionIdx = ELFSection::SHN_COMMON;
|
||||
@ -218,7 +226,7 @@ ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
|
||||
}
|
||||
|
||||
Sym.IsConstant = true;
|
||||
ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags);
|
||||
ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags);
|
||||
Sym.SectionIdx = ElfS.SectionIdx;
|
||||
ElfS.Align = std::max(ElfS.Align, Align);
|
||||
return ElfS;
|
||||
|
@ -118,19 +118,33 @@ namespace llvm {
|
||||
/// is seen, the symbol will move from this list to the SymbolList.
|
||||
SetVector<GlobalValue*> PendingGlobals;
|
||||
|
||||
// Remove tab from section name prefix. This is necessary becase TAI
|
||||
// sometimes return a section name prefixed with a "\t" char. This is
|
||||
// a little bit dirty. FIXME: find a better approach, maybe add more
|
||||
// methods to TAI to get the clean name?
|
||||
void fixNameForSection(std::string &Name) {
|
||||
size_t Pos = Name.find("\t");
|
||||
if (Pos != std::string::npos)
|
||||
Name.erase(Pos, 1);
|
||||
|
||||
Pos = Name.find(".section ");
|
||||
if (Pos != std::string::npos)
|
||||
Name.erase(Pos, 9);
|
||||
|
||||
Pos = Name.find("\n");
|
||||
if (Pos != std::string::npos)
|
||||
Name.erase(Pos, 1);
|
||||
}
|
||||
|
||||
/// getSection - Return the section with the specified name, creating a new
|
||||
/// section if one does not already exist.
|
||||
ELFSection &getSection(const std::string &Name, unsigned Type,
|
||||
unsigned Flags = 0, unsigned Align = 0) {
|
||||
ELFSection *&SN = SectionLookup[Name];
|
||||
if (SN) return *SN;
|
||||
|
||||
// Remove tab from section name prefix. This is necessary becase TAI
|
||||
// sometimes return a section name prefixed with a "\t" char.
|
||||
std::string SectionName(Name);
|
||||
size_t Pos = SectionName.find("\t");
|
||||
if (Pos != std::string::npos)
|
||||
SectionName.erase(Pos, 1);
|
||||
fixNameForSection(SectionName);
|
||||
|
||||
ELFSection *&SN = SectionLookup[SectionName];
|
||||
if (SN) return *SN;
|
||||
|
||||
SectionList.push_back(ELFSection(SectionName, isLittleEndian, is64Bit));
|
||||
SN = &SectionList.back();
|
||||
@ -149,6 +163,12 @@ namespace llvm {
|
||||
ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
|
||||
}
|
||||
|
||||
/// Get jump table section on the section name returned by TAI
|
||||
ELFSection &getJumpTableSection(std::string SName, unsigned Align) {
|
||||
return getSection(SName, ELFSection::SHT_PROGBITS,
|
||||
ELFSection::SHF_ALLOC, Align);
|
||||
}
|
||||
|
||||
/// Get a constant pool section based on the section name returned by TAI
|
||||
ELFSection &getConstantPoolSection(std::string SName, unsigned Align) {
|
||||
return getSection(SName, ELFSection::SHT_PROGBITS,
|
||||
@ -197,9 +217,10 @@ namespace llvm {
|
||||
return getSection("", ELFSection::SHT_NULL, 0);
|
||||
}
|
||||
|
||||
// Helpers for obtaining ELF specific Linkage and Visibility info.
|
||||
// Helpers for obtaining ELF specific info.
|
||||
unsigned getGlobalELFLinkage(const GlobalValue *GV);
|
||||
unsigned getGlobalELFVisibility(const GlobalValue *GV);
|
||||
unsigned getElfSectionFlags(unsigned Flags);
|
||||
|
||||
// As we complete the ELF file, we need to update fields in the ELF header
|
||||
// (e.g. the location of the section table). These members keep track of
|
||||
|
Loading…
Reference in New Issue
Block a user