mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-26 23:55:02 +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)
|
// Emit constant pool to appropriate section(s)
|
||||||
emitConstantPool(MF.getConstantPool());
|
emitConstantPool(MF.getConstantPool());
|
||||||
|
|
||||||
|
// Emit jump tables to appropriate section
|
||||||
|
emitJumpTables(MF.getJumpTableInfo());
|
||||||
|
|
||||||
// Relocations
|
// Relocations
|
||||||
// -----------
|
// -----------
|
||||||
// If we have emitted any relocations to function-specific objects such as
|
// 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());
|
Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex());
|
||||||
MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]);
|
MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]);
|
||||||
MR.setResultPointer((void*)Addr);
|
MR.setResultPointer((void*)Addr);
|
||||||
|
} else if (MR.isJumpTableIndex()) {
|
||||||
|
Addr = getJumpTableEntryAddress(MR.getJumpTableIndex());
|
||||||
|
MR.setResultPointer((void*)Addr);
|
||||||
|
MR.setConstantVal(JumpTableSectionIdx);
|
||||||
} else {
|
} else {
|
||||||
assert(0 && "Unhandled relocation type");
|
assert(0 && "Unhandled relocation type");
|
||||||
}
|
}
|
||||||
ES->addRelocation(MR);
|
ES->addRelocation(MR);
|
||||||
}
|
}
|
||||||
Relocations.clear();
|
|
||||||
|
|
||||||
|
// Clear per-function data structures.
|
||||||
|
Relocations.clear();
|
||||||
|
CPLocations.clear();
|
||||||
|
CPSections.clear();
|
||||||
|
JTLocations.clear();
|
||||||
|
MBBLocations.clear();
|
||||||
return false;
|
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
|
} // end namespace llvm
|
||||||
|
@ -40,6 +40,10 @@ namespace llvm {
|
|||||||
/// containing the constant pool entry for that index.
|
/// containing the constant pool entry for that index.
|
||||||
std::vector<unsigned> CPSections;
|
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.
|
/// MBBLocations - This vector is a mapping from MBB ID's to their address.
|
||||||
/// It is filled in by the StartMachineBasicBlock callback and queried by
|
/// It is filled in by the StartMachineBasicBlock callback and queried by
|
||||||
/// the getMachineBasicBlockAddress callback.
|
/// the getMachineBasicBlockAddress callback.
|
||||||
@ -48,8 +52,12 @@ namespace llvm {
|
|||||||
/// FnStartPtr - Pointer to the start location of the current function
|
/// FnStartPtr - Pointer to the start location of the current function
|
||||||
/// in the buffer
|
/// in the buffer
|
||||||
uint8_t *FnStartPtr;
|
uint8_t *FnStartPtr;
|
||||||
|
|
||||||
|
/// JumpTableSectionIdx - Holds the index of the Jump Table Section
|
||||||
|
unsigned JumpTableSectionIdx;
|
||||||
public:
|
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);
|
void startFunction(MachineFunction &F);
|
||||||
bool finishFunction(MachineFunction &F);
|
bool finishFunction(MachineFunction &F);
|
||||||
@ -64,25 +72,20 @@ namespace llvm {
|
|||||||
MBBLocations[MBB->getNumber()] = getCurrentPCOffset();
|
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 {
|
virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
|
||||||
assert(CPLocations.size() > Index && "CP not emitted!");
|
assert(CPLocations.size() > Index && "CP not emitted!");
|
||||||
return CPLocations[Index];
|
return CPLocations[Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const {
|
virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const {
|
||||||
assert(0 && "JT not implementated yet!");
|
assert(JTLocations.size() > Index && "JT not emitted!");
|
||||||
return 0;
|
return JTLocations[Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const {
|
virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const {
|
||||||
assert(0 && "JT not implementated yet!");
|
assert(MBBLocations.size() > (unsigned)MBB->getNumber() &&
|
||||||
return 0;
|
MBBLocations[MBB->getNumber()] && "MBB not emitted!");
|
||||||
|
return MBBLocations[MBB->getNumber()];
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uintptr_t getLabelAddress(uint64_t Label) const {
|
virtual uintptr_t getLabelAddress(uint64_t Label) const {
|
||||||
@ -100,7 +103,11 @@ namespace llvm {
|
|||||||
/// the constant should live in and emit the constant.
|
/// the constant should live in and emit the constant.
|
||||||
void emitConstantPool(MachineConstantPool *MCP);
|
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!
|
/// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE!
|
||||||
void startGVStub(const GlobalValue* F, unsigned StubSize,
|
void startGVStub(const GlobalValue* F, unsigned StubSize,
|
||||||
|
@ -166,43 +166,51 @@ unsigned ELFWriter::getGlobalELFLinkage(const GlobalValue *GV) {
|
|||||||
return ELFSym::STB_GLOBAL;
|
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
|
// For global symbols without a section, return the Null section as a
|
||||||
// placeholder
|
// placeholder
|
||||||
ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
|
ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
|
||||||
ELFSym &Sym) {
|
ELFSym &Sym) {
|
||||||
const Section *S = TAI->SectionForGlobal(GV);
|
// If this is a declaration, the symbol does not have a section.
|
||||||
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 (!GV->hasInitializer()) {
|
if (!GV->hasInitializer()) {
|
||||||
Sym.SectionIdx = ELFSection::SHN_UNDEF;
|
Sym.SectionIdx = ELFSection::SHN_UNDEF;
|
||||||
return getNullSection();
|
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();
|
const TargetData *TD = TM.getTargetData();
|
||||||
unsigned Align = TD->getPreferredAlignment(GV);
|
unsigned Align = TD->getPreferredAlignment(GV);
|
||||||
Constant *CV = GV->getInitializer();
|
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.
|
// 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
|
// Variables are part of the common block if they are zero initialized
|
||||||
// and allowed to be merged with other symbols.
|
// and allowed to be merged with other symbols.
|
||||||
if (CV->isNullValue() || isa<UndefValue>(CV)) {
|
if (CV->isNullValue() || isa<UndefValue>(CV)) {
|
||||||
SectionType = ELFSection::SHT_NOBITS;
|
SectionType = ELFSection::SHT_NOBITS;
|
||||||
ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags);
|
ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags);
|
||||||
if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
|
if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
|
||||||
GV->hasCommonLinkage()) {
|
GV->hasCommonLinkage()) {
|
||||||
Sym.SectionIdx = ELFSection::SHN_COMMON;
|
Sym.SectionIdx = ELFSection::SHN_COMMON;
|
||||||
@ -218,7 +226,7 @@ ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Sym.IsConstant = true;
|
Sym.IsConstant = true;
|
||||||
ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags);
|
ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags);
|
||||||
Sym.SectionIdx = ElfS.SectionIdx;
|
Sym.SectionIdx = ElfS.SectionIdx;
|
||||||
ElfS.Align = std::max(ElfS.Align, Align);
|
ElfS.Align = std::max(ElfS.Align, Align);
|
||||||
return ElfS;
|
return ElfS;
|
||||||
|
@ -118,19 +118,33 @@ namespace llvm {
|
|||||||
/// is seen, the symbol will move from this list to the SymbolList.
|
/// is seen, the symbol will move from this list to the SymbolList.
|
||||||
SetVector<GlobalValue*> PendingGlobals;
|
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
|
/// getSection - Return the section with the specified name, creating a new
|
||||||
/// section if one does not already exist.
|
/// section if one does not already exist.
|
||||||
ELFSection &getSection(const std::string &Name, unsigned Type,
|
ELFSection &getSection(const std::string &Name, unsigned Type,
|
||||||
unsigned Flags = 0, unsigned Align = 0) {
|
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);
|
std::string SectionName(Name);
|
||||||
size_t Pos = SectionName.find("\t");
|
fixNameForSection(SectionName);
|
||||||
if (Pos != std::string::npos)
|
|
||||||
SectionName.erase(Pos, 1);
|
ELFSection *&SN = SectionLookup[SectionName];
|
||||||
|
if (SN) return *SN;
|
||||||
|
|
||||||
SectionList.push_back(ELFSection(SectionName, isLittleEndian, is64Bit));
|
SectionList.push_back(ELFSection(SectionName, isLittleEndian, is64Bit));
|
||||||
SN = &SectionList.back();
|
SN = &SectionList.back();
|
||||||
@ -149,6 +163,12 @@ namespace llvm {
|
|||||||
ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
|
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
|
/// Get a constant pool section based on the section name returned by TAI
|
||||||
ELFSection &getConstantPoolSection(std::string SName, unsigned Align) {
|
ELFSection &getConstantPoolSection(std::string SName, unsigned Align) {
|
||||||
return getSection(SName, ELFSection::SHT_PROGBITS,
|
return getSection(SName, ELFSection::SHT_PROGBITS,
|
||||||
@ -197,9 +217,10 @@ namespace llvm {
|
|||||||
return getSection("", ELFSection::SHT_NULL, 0);
|
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 getGlobalELFLinkage(const GlobalValue *GV);
|
||||||
unsigned getGlobalELFVisibility(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
|
// 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
|
// (e.g. the location of the section table). These members keep track of
|
||||||
|
Loading…
Reference in New Issue
Block a user