mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-07 14:33:15 +00:00
llvm-mc/Mach-O: Preliminary support for indirect symbols.
- The indirect table itself isn't being filled in yet. - This isn't factored properly and is rather FIXMEd, but at the moment I'm more focused on figuring out what it needs to do. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79910 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
15af79c8f8
commit
0c7761b3f9
@ -16,6 +16,7 @@
|
|||||||
#include "llvm/MC/MCValue.h"
|
#include "llvm/MC/MCValue.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/DataTypes.h"
|
#include "llvm/Support/DataTypes.h"
|
||||||
|
#include <vector> // FIXME: Shouldn't be needed.
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class raw_ostream;
|
class raw_ostream;
|
||||||
@ -360,6 +361,12 @@ public:
|
|||||||
/// @}
|
/// @}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME: This really doesn't belong here. See comments below.
|
||||||
|
struct IndirectSymbolData {
|
||||||
|
MCSymbol *Symbol;
|
||||||
|
MCSectionData *SectionData;
|
||||||
|
};
|
||||||
|
|
||||||
class MCAssembler {
|
class MCAssembler {
|
||||||
public:
|
public:
|
||||||
typedef iplist<MCSectionData> SectionDataListType;
|
typedef iplist<MCSectionData> SectionDataListType;
|
||||||
@ -371,6 +378,8 @@ public:
|
|||||||
typedef SymbolDataListType::const_iterator const_symbol_iterator;
|
typedef SymbolDataListType::const_iterator const_symbol_iterator;
|
||||||
typedef SymbolDataListType::iterator symbol_iterator;
|
typedef SymbolDataListType::iterator symbol_iterator;
|
||||||
|
|
||||||
|
typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT
|
MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT
|
||||||
void operator=(const MCAssembler&); // DO NOT IMPLEMENT
|
void operator=(const MCAssembler&); // DO NOT IMPLEMENT
|
||||||
@ -381,6 +390,8 @@ private:
|
|||||||
|
|
||||||
iplist<MCSymbolData> Symbols;
|
iplist<MCSymbolData> Symbols;
|
||||||
|
|
||||||
|
std::vector<IndirectSymbolData> IndirectSymbols;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// LayoutSection - Assign offsets and sizes to the fragments in the section
|
/// LayoutSection - Assign offsets and sizes to the fragments in the section
|
||||||
/// \arg SD, and update the section size. The section file offset should
|
/// \arg SD, and update the section size. The section file offset should
|
||||||
@ -431,6 +442,27 @@ public:
|
|||||||
|
|
||||||
size_t symbol_size() const { return Symbols.size(); }
|
size_t symbol_size() const { return Symbols.size(); }
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
/// @name Indirect Symbol List Access
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
// FIXME: This is a total hack, this should not be here. Once things are
|
||||||
|
// factored so that the streamer has direct access to the .o writer, it can
|
||||||
|
// disappear.
|
||||||
|
std::vector<IndirectSymbolData> &getIndirectSymbols() {
|
||||||
|
return IndirectSymbols;
|
||||||
|
}
|
||||||
|
|
||||||
|
indirect_symbol_iterator indirect_symbol_begin() {
|
||||||
|
return IndirectSymbols.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
indirect_symbol_iterator indirect_symbol_end() {
|
||||||
|
return IndirectSymbols.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -311,12 +311,68 @@ public:
|
|||||||
Write32(0); // FIXME: Value
|
Write32(0); // FIXME: Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BindIndirectSymbols(MCAssembler &Asm) {
|
||||||
|
// This is the point where 'as' creates actual symbols for indirect symbols
|
||||||
|
// (in the following two passes). It would be easier for us to do this
|
||||||
|
// sooner when we see the attribute, but that makes getting the order in the
|
||||||
|
// symbol table much more complicated than it is worth.
|
||||||
|
//
|
||||||
|
// FIXME: Revisit this when the dust settles.
|
||||||
|
|
||||||
|
// FIXME: This should not be needed.
|
||||||
|
DenseMap<MCSymbol*, MCSymbolData *> SymbolMap;
|
||||||
|
|
||||||
|
for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
|
||||||
|
ie = Asm.symbol_end(); it != ie; ++it)
|
||||||
|
SymbolMap[&it->getSymbol()] = it;
|
||||||
|
|
||||||
|
// Bind non lazy symbol pointers first.
|
||||||
|
for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
|
||||||
|
ie = Asm.indirect_symbol_end(); it != ie; ++it) {
|
||||||
|
// FIXME: cast<> support!
|
||||||
|
const MCSectionMachO &Section =
|
||||||
|
static_cast<const MCSectionMachO&>(it->SectionData->getSection());
|
||||||
|
|
||||||
|
unsigned Type =
|
||||||
|
Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
|
||||||
|
if (Type != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MCSymbolData *&Entry = SymbolMap[it->Symbol];
|
||||||
|
if (!Entry)
|
||||||
|
Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then lazy symbol pointers and symbol stubs.
|
||||||
|
for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
|
||||||
|
ie = Asm.indirect_symbol_end(); it != ie; ++it) {
|
||||||
|
// FIXME: cast<> support!
|
||||||
|
const MCSectionMachO &Section =
|
||||||
|
static_cast<const MCSectionMachO&>(it->SectionData->getSection());
|
||||||
|
|
||||||
|
unsigned Type =
|
||||||
|
Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
|
||||||
|
if (Type != MCSectionMachO::S_LAZY_SYMBOL_POINTERS &&
|
||||||
|
Type != MCSectionMachO::S_SYMBOL_STUBS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MCSymbolData *&Entry = SymbolMap[it->Symbol];
|
||||||
|
if (!Entry) {
|
||||||
|
Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm);
|
||||||
|
|
||||||
|
// Set the symbol type to undefined lazy, but only on construction.
|
||||||
|
//
|
||||||
|
// FIXME: Do not hardcode.
|
||||||
|
Entry->setFlags(Entry->getFlags() | 0x0001);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// ComputeSymbolTable - Compute the symbol table data
|
/// ComputeSymbolTable - Compute the symbol table data
|
||||||
///
|
///
|
||||||
/// \param StringTable [out] - The string table data.
|
/// \param StringTable [out] - The string table data.
|
||||||
/// \param StringIndexMap [out] - Map from symbol names to offsets in the
|
/// \param StringIndexMap [out] - Map from symbol names to offsets in the
|
||||||
/// string table.
|
/// string table.
|
||||||
|
|
||||||
void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
|
void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
|
||||||
std::vector<MachSymbolData> &LocalSymbolData,
|
std::vector<MachSymbolData> &LocalSymbolData,
|
||||||
std::vector<MachSymbolData> &ExternalSymbolData,
|
std::vector<MachSymbolData> &ExternalSymbolData,
|
||||||
@ -414,6 +470,8 @@ public:
|
|||||||
void WriteObject(MCAssembler &Asm) {
|
void WriteObject(MCAssembler &Asm) {
|
||||||
unsigned NumSections = Asm.size();
|
unsigned NumSections = Asm.size();
|
||||||
|
|
||||||
|
BindIndirectSymbols(Asm);
|
||||||
|
|
||||||
// Compute symbol table information.
|
// Compute symbol table information.
|
||||||
SmallString<256> StringTable;
|
SmallString<256> StringTable;
|
||||||
std::vector<MachSymbolData> LocalSymbolData;
|
std::vector<MachSymbolData> LocalSymbolData;
|
||||||
@ -467,22 +525,32 @@ public:
|
|||||||
|
|
||||||
// Write the symbol table load command, if used.
|
// Write the symbol table load command, if used.
|
||||||
if (NumSymbols) {
|
if (NumSymbols) {
|
||||||
// The string table is written after all the section data.
|
|
||||||
uint64_t SymbolTableOffset = SectionDataStartOffset + SectionDataSize;
|
|
||||||
uint64_t StringTableOffset =
|
|
||||||
SymbolTableOffset + NumSymbols * Nlist32Size;
|
|
||||||
WriteSymtabLoadCommand(SymbolTableOffset, NumSymbols,
|
|
||||||
StringTableOffset, StringTable.size());
|
|
||||||
|
|
||||||
unsigned FirstLocalSymbol = 0;
|
unsigned FirstLocalSymbol = 0;
|
||||||
unsigned NumLocalSymbols = LocalSymbolData.size();
|
unsigned NumLocalSymbols = LocalSymbolData.size();
|
||||||
unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
|
unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
|
||||||
unsigned NumExternalSymbols = ExternalSymbolData.size();
|
unsigned NumExternalSymbols = ExternalSymbolData.size();
|
||||||
unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
|
unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
|
||||||
unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
|
unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
|
||||||
// FIXME: Get correct symbol indices and counts for indirect symbols.
|
unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
|
||||||
unsigned IndirectSymbolOffset = 0;
|
unsigned NumSymTabSymbols =
|
||||||
unsigned NumIndirectSymbols = 0;
|
NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
|
||||||
|
uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
|
||||||
|
uint64_t IndirectSymbolOffset = 0;
|
||||||
|
|
||||||
|
// If used, the indirect symbols are written after the section data.
|
||||||
|
if (NumIndirectSymbols)
|
||||||
|
IndirectSymbolOffset = SectionDataStartOffset + SectionDataSize;
|
||||||
|
|
||||||
|
// The symbol table is written after the indirect symbol data.
|
||||||
|
uint64_t SymbolTableOffset =
|
||||||
|
SectionDataStartOffset + SectionDataSize + IndirectSymbolSize;
|
||||||
|
|
||||||
|
// The string table is written after symbol table.
|
||||||
|
uint64_t StringTableOffset =
|
||||||
|
SymbolTableOffset + NumSymTabSymbols * Nlist32Size;
|
||||||
|
WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
|
||||||
|
StringTableOffset, StringTable.size());
|
||||||
|
|
||||||
WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
|
WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
|
||||||
FirstExternalSymbol, NumExternalSymbols,
|
FirstExternalSymbol, NumExternalSymbols,
|
||||||
FirstUndefinedSymbol, NumUndefinedSymbols,
|
FirstUndefinedSymbol, NumUndefinedSymbols,
|
||||||
@ -495,9 +563,13 @@ public:
|
|||||||
|
|
||||||
// Write the symbol table data, if used.
|
// Write the symbol table data, if used.
|
||||||
if (NumSymbols) {
|
if (NumSymbols) {
|
||||||
// FIXME: Check that offsets match computed ones.
|
// Write the indirect symbol entries.
|
||||||
|
//
|
||||||
|
// FIXME: We need the symbol index map for this.
|
||||||
|
for (unsigned i = 0, e = Asm.indirect_symbol_size(); i != e; ++i)
|
||||||
|
Write32(0);
|
||||||
|
|
||||||
// FIXME: Some of these are ordered by name to help the linker.
|
// FIXME: Check that offsets match computed ones.
|
||||||
|
|
||||||
// Write the symbol table entries.
|
// Write the symbol table entries.
|
||||||
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
|
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
|
||||||
|
@ -165,6 +165,16 @@ void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol,
|
|||||||
|
|
||||||
void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
|
void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
|
||||||
SymbolAttr Attribute) {
|
SymbolAttr Attribute) {
|
||||||
|
// Indirect symbols are handled differently, to match how 'as' handles
|
||||||
|
// them. This makes writing matching .o files easier.
|
||||||
|
if (Attribute == MCStreamer::IndirectSymbol) {
|
||||||
|
IndirectSymbolData ISD;
|
||||||
|
ISD.Symbol = Symbol;
|
||||||
|
ISD.SectionData = CurSectionData;
|
||||||
|
Assembler.getIndirectSymbols().push_back(ISD);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Adding a symbol attribute always introduces the symbol, note that an
|
// Adding a symbol attribute always introduces the symbol, note that an
|
||||||
// important side effect of calling getSymbolData here is to register the
|
// important side effect of calling getSymbolData here is to register the
|
||||||
// symbol with the assembler.
|
// symbol with the assembler.
|
||||||
@ -177,6 +187,7 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
|
|||||||
// In the future it might be worth trying to make these operations more well
|
// In the future it might be worth trying to make these operations more well
|
||||||
// defined.
|
// defined.
|
||||||
switch (Attribute) {
|
switch (Attribute) {
|
||||||
|
case MCStreamer::IndirectSymbol:
|
||||||
case MCStreamer::Hidden:
|
case MCStreamer::Hidden:
|
||||||
case MCStreamer::Internal:
|
case MCStreamer::Internal:
|
||||||
case MCStreamer::Protected:
|
case MCStreamer::Protected:
|
||||||
@ -195,10 +206,6 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
|
|||||||
SD.setFlags(SD.getFlags() | SF_ReferenceTypeUndefinedLazy);
|
SD.setFlags(SD.getFlags() | SF_ReferenceTypeUndefinedLazy);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MCStreamer::IndirectSymbol:
|
|
||||||
llvm_unreachable("FIXME: Not yet implemented!");
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Since .reference sets the no dead strip bit, it is equivalent to
|
// Since .reference sets the no dead strip bit, it is equivalent to
|
||||||
// .no_dead_strip in practice.
|
// .no_dead_strip in practice.
|
||||||
case MCStreamer::Reference:
|
case MCStreamer::Reference:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user