mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-10-10 16:24:04 +00:00
Cleanup the global emission and refactor some code
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75537 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
db1cd5eba5
commit
d291066879
@ -126,13 +126,9 @@ namespace llvm {
|
|||||||
/// added to logical symbol table for the module. This is eventually
|
/// added to logical symbol table for the module. This is eventually
|
||||||
/// turned into a real symbol table in the file.
|
/// turned into a real symbol table in the file.
|
||||||
struct ELFSym {
|
struct ELFSym {
|
||||||
// The global value this corresponds to. Global symbols can be on of the
|
// The global value this symbol matches. This should be null if the symbol
|
||||||
// 3 types : if this symbol has a zero initializer, it is common or should
|
// is not a global value.
|
||||||
// be placed in bss section otherwise it's a constant.
|
|
||||||
const GlobalValue *GV;
|
const GlobalValue *GV;
|
||||||
bool IsCommon;
|
|
||||||
bool IsBss;
|
|
||||||
bool IsConstant;
|
|
||||||
|
|
||||||
// ELF specific fields
|
// ELF specific fields
|
||||||
unsigned NameIdx; // Index in .strtab of name, once emitted.
|
unsigned NameIdx; // Index in .strtab of name, once emitted.
|
||||||
@ -145,18 +141,18 @@ namespace llvm {
|
|||||||
// Symbol index into the Symbol table
|
// Symbol index into the Symbol table
|
||||||
unsigned SymTabIdx;
|
unsigned SymTabIdx;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
STB_LOCAL = 0,
|
STB_LOCAL = 0,
|
||||||
STB_GLOBAL = 1,
|
STB_GLOBAL = 1,
|
||||||
STB_WEAK = 2
|
STB_WEAK = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
STT_NOTYPE = 0,
|
STT_NOTYPE = 0,
|
||||||
STT_OBJECT = 1,
|
STT_OBJECT = 1,
|
||||||
STT_FUNC = 2,
|
STT_FUNC = 2,
|
||||||
STT_SECTION = 3,
|
STT_SECTION = 3,
|
||||||
STT_FILE = 4
|
STT_FILE = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -166,8 +162,7 @@ namespace llvm {
|
|||||||
STV_PROTECTED = 3 // Visible in other components but not preemptable
|
STV_PROTECTED = 3 // Visible in other components but not preemptable
|
||||||
};
|
};
|
||||||
|
|
||||||
ELFSym(const GlobalValue *gv) : GV(gv), IsCommon(false), IsBss(false),
|
ELFSym(const GlobalValue *gv) : GV(gv), NameIdx(0), Value(0),
|
||||||
IsConstant(false), NameIdx(0), Value(0),
|
|
||||||
Size(0), Info(0), Other(STV_DEFAULT),
|
Size(0), Info(0), Other(STV_DEFAULT),
|
||||||
SectionIdx(ELFSection::SHN_UNDEF),
|
SectionIdx(ELFSection::SHN_UNDEF),
|
||||||
SymTabIdx(0) {}
|
SymTabIdx(0) {}
|
||||||
|
@ -62,7 +62,7 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
|||||||
const Function *F = MF.getFunction();
|
const Function *F = MF.getFunction();
|
||||||
ELFSym FnSym(F);
|
ELFSym FnSym(F);
|
||||||
FnSym.setType(ELFSym::STT_FUNC);
|
FnSym.setType(ELFSym::STT_FUNC);
|
||||||
FnSym.setBind(EW.getGlobalELFLinkage(F));
|
FnSym.setBind(EW.getGlobalELFBinding(F));
|
||||||
FnSym.setVisibility(EW.getGlobalELFVisibility(F));
|
FnSym.setVisibility(EW.getGlobalELFVisibility(F));
|
||||||
FnSym.SectionIdx = ES->SectionIdx;
|
FnSym.SectionIdx = ES->SectionIdx;
|
||||||
FnSym.Size = ES->getCurrentPCOffset()-FnStartOff;
|
FnSym.Size = ES->getCurrentPCOffset()-FnStartOff;
|
||||||
|
@ -145,6 +145,7 @@ bool ELFWriter::doInitialization(Module &M) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getGlobalELFVisibility - Returns the ELF specific visibility type
|
||||||
unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) {
|
unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) {
|
||||||
switch (GV->getVisibility()) {
|
switch (GV->getVisibility()) {
|
||||||
default:
|
default:
|
||||||
@ -156,11 +157,11 @@ unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) {
|
|||||||
case GlobalValue::ProtectedVisibility:
|
case GlobalValue::ProtectedVisibility:
|
||||||
return ELFSym::STV_PROTECTED;
|
return ELFSym::STV_PROTECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned ELFWriter::getGlobalELFLinkage(const GlobalValue *GV) {
|
// getGlobalELFBinding - Returns the ELF specific binding type
|
||||||
|
unsigned ELFWriter::getGlobalELFBinding(const GlobalValue *GV) {
|
||||||
if (GV->hasInternalLinkage())
|
if (GV->hasInternalLinkage())
|
||||||
return ELFSym::STB_LOCAL;
|
return ELFSym::STB_LOCAL;
|
||||||
|
|
||||||
@ -170,8 +171,19 @@ unsigned ELFWriter::getGlobalELFLinkage(const GlobalValue *GV) {
|
|||||||
return ELFSym::STB_GLOBAL;
|
return ELFSym::STB_GLOBAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// getElfSectionFlags - Get the ELF Section Header based on the
|
// getGlobalELFType - Returns the ELF specific type for a global
|
||||||
// flags defined in ELFTargetAsmInfo.
|
unsigned ELFWriter::getGlobalELFType(const GlobalValue *GV) {
|
||||||
|
if (GV->isDeclaration())
|
||||||
|
return ELFSym::STT_NOTYPE;
|
||||||
|
|
||||||
|
if (isa<Function>(GV))
|
||||||
|
return ELFSym::STT_FUNC;
|
||||||
|
|
||||||
|
return ELFSym::STT_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// getElfSectionFlags - Get the ELF Section Header flags based
|
||||||
|
// on the flags defined in ELFTargetAsmInfo.
|
||||||
unsigned ELFWriter::getElfSectionFlags(unsigned Flags) {
|
unsigned ELFWriter::getElfSectionFlags(unsigned Flags) {
|
||||||
unsigned ElfSectionFlags = ELFSection::SHF_ALLOC;
|
unsigned ElfSectionFlags = ELFSection::SHF_ALLOC;
|
||||||
|
|
||||||
@ -189,92 +201,99 @@ unsigned ELFWriter::getElfSectionFlags(unsigned Flags) {
|
|||||||
return ElfSectionFlags;
|
return ElfSectionFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For global symbols without a section, return the Null section as a
|
// isELFUndefSym - the symbol has no section and must be placed in
|
||||||
// placeholder
|
// the symbol table with a reference to the null section.
|
||||||
ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
|
static bool isELFUndefSym(const GlobalValue *GV) {
|
||||||
ELFSym &Sym) {
|
return GV->isDeclaration();
|
||||||
// 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 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, SectionFlags);
|
|
||||||
if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
|
|
||||||
GV->hasCommonLinkage()) {
|
|
||||||
Sym.SectionIdx = ELFSection::SHN_COMMON;
|
|
||||||
Sym.IsCommon = true;
|
|
||||||
ElfS.Align = 1;
|
|
||||||
return ElfS;
|
|
||||||
}
|
|
||||||
Sym.IsBss = true;
|
|
||||||
Sym.SectionIdx = ElfS.SectionIdx;
|
|
||||||
if (Align) ElfS.Size = (ElfS.Size + Align-1) & ~(Align-1);
|
|
||||||
ElfS.Align = std::max(ElfS.Align, Align);
|
|
||||||
return ElfS;
|
|
||||||
}
|
|
||||||
|
|
||||||
Sym.IsConstant = true;
|
|
||||||
ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags);
|
|
||||||
Sym.SectionIdx = ElfS.SectionIdx;
|
|
||||||
ElfS.Align = std::max(ElfS.Align, Align);
|
|
||||||
return ElfS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ELFWriter::EmitFunctionDeclaration(const Function *F) {
|
// isELFBssSym - for an undef or null value, the symbol must go to a bss
|
||||||
ELFSym GblSym(F);
|
// section if it's not weak for linker, otherwise it's a common sym.
|
||||||
GblSym.setBind(ELFSym::STB_GLOBAL);
|
static bool isELFBssSym(const GlobalValue *GV) {
|
||||||
GblSym.setType(ELFSym::STT_NOTYPE);
|
return (!GV->isDeclaration() &&
|
||||||
GblSym.setVisibility(ELFSym::STV_DEFAULT);
|
(GV->isNullValue() || isa<UndefValue>(GV)) &&
|
||||||
GblSym.SectionIdx = ELFSection::SHN_UNDEF;
|
!GV->isWeakForLinker());
|
||||||
SymbolList.push_back(GblSym);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ELFWriter::EmitGlobalVar(const GlobalVariable *GV) {
|
// isELFCommonSym - for an undef or null value, the symbol must go to a
|
||||||
unsigned SymBind = getGlobalELFLinkage(GV);
|
// common section if it's weak for linker, otherwise bss.
|
||||||
unsigned Align=0, Size=0;
|
static bool isELFCommonSym(const GlobalValue *GV) {
|
||||||
|
return (!GV->isDeclaration() &&
|
||||||
|
(GV->isNullValue() || isa<UndefValue>(GV))
|
||||||
|
&& GV->isWeakForLinker());
|
||||||
|
}
|
||||||
|
|
||||||
|
// isELFDataSym - if the symbol is an initialized but no null constant
|
||||||
|
// it must go to some kind of data section gathered from TAI
|
||||||
|
static bool isELFDataSym(const GlobalValue *GV) {
|
||||||
|
return (!GV->isDeclaration() &&
|
||||||
|
!(GV->isNullValue() || isa<UndefValue>(GV)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmitGlobal - Choose the right section for global and emit it
|
||||||
|
void ELFWriter::EmitGlobal(const GlobalValue *GV) {
|
||||||
|
|
||||||
|
// Handle ELF Bind, Visibility and Type for the current symbol
|
||||||
|
unsigned SymBind = getGlobalELFBinding(GV);
|
||||||
ELFSym GblSym(GV);
|
ELFSym GblSym(GV);
|
||||||
GblSym.setBind(SymBind);
|
GblSym.setBind(SymBind);
|
||||||
GblSym.setVisibility(getGlobalELFVisibility(GV));
|
GblSym.setVisibility(getGlobalELFVisibility(GV));
|
||||||
|
GblSym.setType(getGlobalELFType(GV));
|
||||||
|
|
||||||
if (GV->hasInitializer()) {
|
if (isELFUndefSym(GV)) {
|
||||||
GblSym.setType(ELFSym::STT_OBJECT);
|
GblSym.SectionIdx = ELFSection::SHN_UNDEF;
|
||||||
const TargetData *TD = TM.getTargetData();
|
|
||||||
Align = TD->getPreferredAlignment(GV);
|
|
||||||
Size = TD->getTypeAllocSize(GV->getInitializer()->getType());
|
|
||||||
GblSym.Size = Size;
|
|
||||||
} else {
|
} else {
|
||||||
GblSym.setType(ELFSym::STT_NOTYPE);
|
assert(isa<GlobalVariable>(GV) && "GV not a global variable!");
|
||||||
}
|
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
|
||||||
|
|
||||||
ELFSection &GblSection = getGlobalSymELFSection(GV, GblSym);
|
// Get ELF section from TAI
|
||||||
|
const Section *S = TAI->SectionForGlobal(GV);
|
||||||
|
unsigned SectionFlags = getElfSectionFlags(S->getFlags());
|
||||||
|
|
||||||
if (GblSym.IsCommon) {
|
// The symbol align should update the section alignment if needed
|
||||||
GblSym.Value = Align;
|
const TargetData *TD = TM.getTargetData();
|
||||||
} else if (GblSym.IsBss) {
|
unsigned Align = TD->getPreferredAlignment(GVar);
|
||||||
GblSym.Value = GblSection.Size;
|
unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType());
|
||||||
GblSection.Size += Size;
|
GblSym.Size = Size;
|
||||||
} else if (GblSym.IsConstant){
|
|
||||||
// GblSym.Value should contain the symbol index inside the section,
|
if (isELFCommonSym(GV)) {
|
||||||
// and all symbols should start on their required alignment boundary
|
GblSym.SectionIdx = ELFSection::SHN_COMMON;
|
||||||
GblSym.Value = (GblSection.size() + (Align-1)) & (-Align);
|
getSection(S->getName(), ELFSection::SHT_NOBITS, SectionFlags, 1);
|
||||||
GblSection.emitAlignment(Align);
|
|
||||||
EmitGlobalConstant(GV->getInitializer(), GblSection);
|
// A new linkonce section is created for each global in the
|
||||||
|
// common section, the default alignment is 1 and the symbol
|
||||||
|
// value contains its alignment.
|
||||||
|
GblSym.Value = Align;
|
||||||
|
|
||||||
|
} else if (isELFBssSym(GV)) {
|
||||||
|
ELFSection &ES =
|
||||||
|
getSection(S->getName(), ELFSection::SHT_NOBITS, SectionFlags);
|
||||||
|
GblSym.SectionIdx = ES.SectionIdx;
|
||||||
|
|
||||||
|
// Update the size with alignment and the next object can
|
||||||
|
// start in the right offset in the section
|
||||||
|
if (Align) ES.Size = (ES.Size + Align-1) & ~(Align-1);
|
||||||
|
ES.Align = std::max(ES.Align, Align);
|
||||||
|
|
||||||
|
// GblSym.Value should contain the virtual offset inside the section.
|
||||||
|
// Virtual because the BSS space is not allocated on ELF objects
|
||||||
|
GblSym.Value = ES.Size;
|
||||||
|
ES.Size += Size;
|
||||||
|
|
||||||
|
} else if (isELFDataSym(GV)) {
|
||||||
|
ELFSection &ES =
|
||||||
|
getSection(S->getName(), ELFSection::SHT_PROGBITS, SectionFlags);
|
||||||
|
GblSym.SectionIdx = ES.SectionIdx;
|
||||||
|
|
||||||
|
// GblSym.Value should contain the symbol offset inside the section,
|
||||||
|
// and all symbols should start on their required alignment boundary
|
||||||
|
ES.Align = std::max(ES.Align, Align);
|
||||||
|
GblSym.Value = (ES.size() + (Align-1)) & (-Align);
|
||||||
|
ES.emitAlignment(ES.Align);
|
||||||
|
|
||||||
|
// Emit the global to the data section 'ES'
|
||||||
|
EmitGlobalConstant(GVar->getInitializer(), ES);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Local symbols should come first on the symbol table.
|
// Local symbols should come first on the symbol table.
|
||||||
@ -379,7 +398,7 @@ bool ELFWriter::doFinalization(Module &M) {
|
|||||||
// Build and emit data, bss and "common" sections.
|
// Build and emit data, bss and "common" sections.
|
||||||
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
EmitGlobalVar(I);
|
EmitGlobal(I);
|
||||||
GblSymLookup[I] = 0;
|
GblSymLookup[I] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,15 +411,7 @@ bool ELFWriter::doFinalization(Module &M) {
|
|||||||
if (GblSymLookup.find(*I) != GblSymLookup.end())
|
if (GblSymLookup.find(*I) != GblSymLookup.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) {
|
EmitGlobal(*I);
|
||||||
EmitGlobalVar(GV);
|
|
||||||
} else if (Function *F = dyn_cast<Function>(*I)) {
|
|
||||||
// If function is not in GblSymLookup, it doesn't have a body,
|
|
||||||
// so emit the symbol as a function declaration (no section associated)
|
|
||||||
EmitFunctionDeclaration(F);
|
|
||||||
} else {
|
|
||||||
assert("unknown howto handle pending global");
|
|
||||||
}
|
|
||||||
GblSymLookup[*I] = 0;
|
GblSymLookup[*I] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +499,7 @@ void ELFWriter::EmitRelocations() {
|
|||||||
// Target specific ELF relocation type
|
// Target specific ELF relocation type
|
||||||
unsigned RelType = TEW->getRelocationType(MR.getRelocationType());
|
unsigned RelType = TEW->getRelocationType(MR.getRelocationType());
|
||||||
|
|
||||||
// Constant addend used to compute the value to be stored
|
// Constant addend used to compute the value to be stored
|
||||||
// into the relocatable field
|
// into the relocatable field
|
||||||
int64_t Addend = 0;
|
int64_t Addend = 0;
|
||||||
|
|
||||||
@ -548,7 +559,7 @@ void ELFWriter::EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym) {
|
|||||||
|
|
||||||
/// EmitSectionHeader - Write section 'Section' header in 'SHdrTab'
|
/// EmitSectionHeader - Write section 'Section' header in 'SHdrTab'
|
||||||
/// Section Header Table
|
/// Section Header Table
|
||||||
void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab,
|
void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab,
|
||||||
const ELFSection &SHdr) {
|
const ELFSection &SHdr) {
|
||||||
SHdrTab.emitWord32(SHdr.NameIdx);
|
SHdrTab.emitWord32(SHdr.NameIdx);
|
||||||
SHdrTab.emitWord32(SHdr.Type);
|
SHdrTab.emitWord32(SHdr.Type);
|
||||||
|
@ -218,7 +218,8 @@ namespace llvm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helpers for obtaining ELF specific info.
|
// Helpers for obtaining ELF specific info.
|
||||||
unsigned getGlobalELFLinkage(const GlobalValue *GV);
|
unsigned getGlobalELFBinding(const GlobalValue *GV);
|
||||||
|
unsigned getGlobalELFType(const GlobalValue *GV);
|
||||||
unsigned getGlobalELFVisibility(const GlobalValue *GV);
|
unsigned getGlobalELFVisibility(const GlobalValue *GV);
|
||||||
unsigned getElfSectionFlags(unsigned Flags);
|
unsigned getElfSectionFlags(unsigned Flags);
|
||||||
|
|
||||||
@ -231,8 +232,7 @@ namespace llvm {
|
|||||||
unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header.
|
unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EmitFunctionDeclaration(const Function *F);
|
void EmitGlobal(const GlobalValue *GV);
|
||||||
void EmitGlobalVar(const GlobalVariable *GV);
|
|
||||||
void EmitGlobalConstant(const Constant *C, ELFSection &GblS);
|
void EmitGlobalConstant(const Constant *C, ELFSection &GblS);
|
||||||
void EmitGlobalConstantStruct(const ConstantStruct *CVS,
|
void EmitGlobalConstantStruct(const ConstantStruct *CVS,
|
||||||
ELFSection &GblS);
|
ELFSection &GblS);
|
||||||
|
Loading…
Reference in New Issue
Block a user