aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2009-07-13 22:40:39 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2009-07-13 22:40:39 +0000
commitd291066879ea4e577572fdbb22ba142826c98ccd (patch)
tree809d42bb044c570bc348aeac7ed49c56bd359b8b /lib
parentdb1cd5eba551bdd3d7767207891b578f61f8b39d (diff)
downloadexternal_llvm-d291066879ea4e577572fdbb22ba142826c98ccd.zip
external_llvm-d291066879ea4e577572fdbb22ba142826c98ccd.tar.gz
external_llvm-d291066879ea4e577572fdbb22ba142826c98ccd.tar.bz2
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
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/ELF.h17
-rw-r--r--lib/CodeGen/ELFCodeEmitter.cpp2
-rw-r--r--lib/CodeGen/ELFWriter.cpp189
-rw-r--r--lib/CodeGen/ELFWriter.h6
4 files changed, 110 insertions, 104 deletions
diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h
index 7e983a4..2c37c57 100644
--- a/lib/CodeGen/ELF.h
+++ b/lib/CodeGen/ELF.h
@@ -126,13 +126,9 @@ namespace llvm {
/// added to logical symbol table for the module. This is eventually
/// turned into a real symbol table in the file.
struct ELFSym {
- // The global value this corresponds to. Global symbols can be on of the
- // 3 types : if this symbol has a zero initializer, it is common or should
- // be placed in bss section otherwise it's a constant.
+ // The global value this symbol matches. This should be null if the symbol
+ // is not a global value.
const GlobalValue *GV;
- bool IsCommon;
- bool IsBss;
- bool IsConstant;
// ELF specific fields
unsigned NameIdx; // Index in .strtab of name, once emitted.
@@ -145,18 +141,18 @@ namespace llvm {
// Symbol index into the Symbol table
unsigned SymTabIdx;
- enum {
+ enum {
STB_LOCAL = 0,
STB_GLOBAL = 1,
STB_WEAK = 2
};
- enum {
+ enum {
STT_NOTYPE = 0,
STT_OBJECT = 1,
STT_FUNC = 2,
STT_SECTION = 3,
- STT_FILE = 4
+ STT_FILE = 4
};
enum {
@@ -166,8 +162,7 @@ namespace llvm {
STV_PROTECTED = 3 // Visible in other components but not preemptable
};
- ELFSym(const GlobalValue *gv) : GV(gv), IsCommon(false), IsBss(false),
- IsConstant(false), NameIdx(0), Value(0),
+ ELFSym(const GlobalValue *gv) : GV(gv), NameIdx(0), Value(0),
Size(0), Info(0), Other(STV_DEFAULT),
SectionIdx(ELFSection::SHN_UNDEF),
SymTabIdx(0) {}
diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp
index 07aa1cb..57dc41f 100644
--- a/lib/CodeGen/ELFCodeEmitter.cpp
+++ b/lib/CodeGen/ELFCodeEmitter.cpp
@@ -62,7 +62,7 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
const Function *F = MF.getFunction();
ELFSym FnSym(F);
FnSym.setType(ELFSym::STT_FUNC);
- FnSym.setBind(EW.getGlobalELFLinkage(F));
+ FnSym.setBind(EW.getGlobalELFBinding(F));
FnSym.setVisibility(EW.getGlobalELFVisibility(F));
FnSym.SectionIdx = ES->SectionIdx;
FnSym.Size = ES->getCurrentPCOffset()-FnStartOff;
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index 1318017..a26f93b 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/lib/CodeGen/ELFWriter.cpp
@@ -145,6 +145,7 @@ bool ELFWriter::doInitialization(Module &M) {
return false;
}
+// getGlobalELFVisibility - Returns the ELF specific visibility type
unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) {
switch (GV->getVisibility()) {
default:
@@ -156,11 +157,11 @@ unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) {
case GlobalValue::ProtectedVisibility:
return ELFSym::STV_PROTECTED;
}
-
return 0;
}
-unsigned ELFWriter::getGlobalELFLinkage(const GlobalValue *GV) {
+// getGlobalELFBinding - Returns the ELF specific binding type
+unsigned ELFWriter::getGlobalELFBinding(const GlobalValue *GV) {
if (GV->hasInternalLinkage())
return ELFSym::STB_LOCAL;
@@ -170,8 +171,19 @@ unsigned ELFWriter::getGlobalELFLinkage(const GlobalValue *GV) {
return ELFSym::STB_GLOBAL;
}
-// getElfSectionFlags - Get the ELF Section Header based on the
-// flags defined in ELFTargetAsmInfo.
+// getGlobalELFType - Returns the ELF specific type for a global
+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 ElfSectionFlags = ELFSection::SHF_ALLOC;
@@ -189,92 +201,99 @@ unsigned ELFWriter::getElfSectionFlags(unsigned Flags) {
return ElfSectionFlags;
}
-// For global symbols without a section, return the Null section as a
-// placeholder
-ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
- ELFSym &Sym) {
- // 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";
+// isELFUndefSym - the symbol has no section and must be placed in
+// the symbol table with a reference to the null section.
+static bool isELFUndefSym(const GlobalValue *GV) {
+ return GV->isDeclaration();
+}
- 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;
- }
+// isELFBssSym - for an undef or null value, the symbol must go to a bss
+// section if it's not weak for linker, otherwise it's a common sym.
+static bool isELFBssSym(const GlobalValue *GV) {
+ return (!GV->isDeclaration() &&
+ (GV->isNullValue() || isa<UndefValue>(GV)) &&
+ !GV->isWeakForLinker());
+}
- Sym.IsConstant = true;
- ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags);
- Sym.SectionIdx = ElfS.SectionIdx;
- ElfS.Align = std::max(ElfS.Align, Align);
- return ElfS;
+// isELFCommonSym - for an undef or null value, the symbol must go to a
+// common section if it's weak for linker, otherwise bss.
+static bool isELFCommonSym(const GlobalValue *GV) {
+ return (!GV->isDeclaration() &&
+ (GV->isNullValue() || isa<UndefValue>(GV))
+ && GV->isWeakForLinker());
}
-void ELFWriter::EmitFunctionDeclaration(const Function *F) {
- ELFSym GblSym(F);
- GblSym.setBind(ELFSym::STB_GLOBAL);
- GblSym.setType(ELFSym::STT_NOTYPE);
- GblSym.setVisibility(ELFSym::STV_DEFAULT);
- GblSym.SectionIdx = ELFSection::SHN_UNDEF;
- SymbolList.push_back(GblSym);
+// 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)));
}
-void ELFWriter::EmitGlobalVar(const GlobalVariable *GV) {
- unsigned SymBind = getGlobalELFLinkage(GV);
- unsigned Align=0, Size=0;
+// 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);
GblSym.setBind(SymBind);
GblSym.setVisibility(getGlobalELFVisibility(GV));
+ GblSym.setType(getGlobalELFType(GV));
+
+ if (isELFUndefSym(GV)) {
+ GblSym.SectionIdx = ELFSection::SHN_UNDEF;
+ } else {
+ assert(isa<GlobalVariable>(GV) && "GV not a global variable!");
+ const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
+
+ // Get ELF section from TAI
+ const Section *S = TAI->SectionForGlobal(GV);
+ unsigned SectionFlags = getElfSectionFlags(S->getFlags());
- if (GV->hasInitializer()) {
- GblSym.setType(ELFSym::STT_OBJECT);
+ // The symbol align should update the section alignment if needed
const TargetData *TD = TM.getTargetData();
- Align = TD->getPreferredAlignment(GV);
- Size = TD->getTypeAllocSize(GV->getInitializer()->getType());
+ unsigned Align = TD->getPreferredAlignment(GVar);
+ unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType());
GblSym.Size = Size;
- } else {
- GblSym.setType(ELFSym::STT_NOTYPE);
- }
- ELFSection &GblSection = getGlobalSymELFSection(GV, GblSym);
-
- if (GblSym.IsCommon) {
- GblSym.Value = Align;
- } else if (GblSym.IsBss) {
- GblSym.Value = GblSection.Size;
- GblSection.Size += Size;
- } else if (GblSym.IsConstant){
- // GblSym.Value should contain the symbol index inside the section,
- // and all symbols should start on their required alignment boundary
- GblSym.Value = (GblSection.size() + (Align-1)) & (-Align);
- GblSection.emitAlignment(Align);
- EmitGlobalConstant(GV->getInitializer(), GblSection);
+ if (isELFCommonSym(GV)) {
+ GblSym.SectionIdx = ELFSection::SHN_COMMON;
+ getSection(S->getName(), ELFSection::SHT_NOBITS, SectionFlags, 1);
+
+ // 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.
@@ -379,7 +398,7 @@ bool ELFWriter::doFinalization(Module &M) {
// Build and emit data, bss and "common" sections.
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
- EmitGlobalVar(I);
+ EmitGlobal(I);
GblSymLookup[I] = 0;
}
@@ -392,15 +411,7 @@ bool ELFWriter::doFinalization(Module &M) {
if (GblSymLookup.find(*I) != GblSymLookup.end())
continue;
- if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*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");
- }
+ EmitGlobal(*I);
GblSymLookup[*I] = 0;
}
@@ -488,7 +499,7 @@ void ELFWriter::EmitRelocations() {
// Target specific ELF relocation type
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
int64_t Addend = 0;
@@ -548,7 +559,7 @@ void ELFWriter::EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym) {
/// EmitSectionHeader - Write section 'Section' header in 'SHdrTab'
/// Section Header Table
-void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab,
+void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab,
const ELFSection &SHdr) {
SHdrTab.emitWord32(SHdr.NameIdx);
SHdrTab.emitWord32(SHdr.Type);
diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h
index 1317880..b0d7f3b 100644
--- a/lib/CodeGen/ELFWriter.h
+++ b/lib/CodeGen/ELFWriter.h
@@ -218,7 +218,8 @@ namespace llvm {
}
// 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 getElfSectionFlags(unsigned Flags);
@@ -231,8 +232,7 @@ namespace llvm {
unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header.
private:
- void EmitFunctionDeclaration(const Function *F);
- void EmitGlobalVar(const GlobalVariable *GV);
+ void EmitGlobal(const GlobalValue *GV);
void EmitGlobalConstant(const Constant *C, ELFSection &GblS);
void EmitGlobalConstantStruct(const ConstantStruct *CVS,
ELFSection &GblS);