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:
Bruno Cardoso Lopes 2009-07-03 04:36:26 +00:00
parent 2373c99433
commit 0b1308f189
4 changed files with 142 additions and 42 deletions

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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