[llvm-commits] [llvm] r75537 - in /llvm/trunk/lib/CodeGen: ELF.h ELFCodeEmitter.cpp ELFWriter.cpp ELFWriter.h

Bruno Cardoso Lopes bruno.cardoso at gmail.com
Mon Jul 13 15:40:39 PDT 2009


Author: bruno
Date: Mon Jul 13 17:40:39 2009
New Revision: 75537

URL: http://llvm.org/viewvc/llvm-project?rev=75537&view=rev
Log:
Cleanup the global emission and refactor some code

Modified:
    llvm/trunk/lib/CodeGen/ELF.h
    llvm/trunk/lib/CodeGen/ELFCodeEmitter.cpp
    llvm/trunk/lib/CodeGen/ELFWriter.cpp
    llvm/trunk/lib/CodeGen/ELFWriter.h

Modified: llvm/trunk/lib/CodeGen/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ELF.h?rev=75537&r1=75536&r2=75537&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/ELF.h (original)
+++ llvm/trunk/lib/CodeGen/ELF.h Mon Jul 13 17:40:39 2009
@@ -126,13 +126,9 @@
   /// 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 @@
     // 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 @@
       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) {}

Modified: llvm/trunk/lib/CodeGen/ELFCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ELFCodeEmitter.cpp?rev=75537&r1=75536&r2=75537&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/ELFCodeEmitter.cpp (original)
+++ llvm/trunk/lib/CodeGen/ELFCodeEmitter.cpp Mon Jul 13 17:40:39 2009
@@ -62,7 +62,7 @@
   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;

Modified: llvm/trunk/lib/CodeGen/ELFWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ELFWriter.cpp?rev=75537&r1=75536&r2=75537&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/ELFWriter.cpp (original)
+++ llvm/trunk/lib/CodeGen/ELFWriter.cpp Mon Jul 13 17:40:39 2009
@@ -145,6 +145,7 @@
   return false;
 }
 
+// getGlobalELFVisibility - Returns the ELF specific visibility type
 unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) {
   switch (GV->getVisibility()) {
   default:
@@ -156,11 +157,11 @@
   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 @@
   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 @@
   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();
-  }
+// 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();
+}
 
-  // 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";
+// 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());
+}
 
-  const TargetData *TD = TM.getTargetData();
-  unsigned Align = TD->getPreferredAlignment(GV);
-  Constant *CV = GV->getInitializer();
+// 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());
+}
 
-  // 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) {
-  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);
-}
-
-void ELFWriter::EmitGlobalVar(const GlobalVariable *GV) {
-  unsigned SymBind = getGlobalELFLinkage(GV);
-  unsigned Align=0, Size=0;
+// 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);
   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 (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);
 
-  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);
+      // 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 @@
   // 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 @@
     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 @@
       // 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 @@
 
 /// 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);

Modified: llvm/trunk/lib/CodeGen/ELFWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ELFWriter.h?rev=75537&r1=75536&r2=75537&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/ELFWriter.h (original)
+++ llvm/trunk/lib/CodeGen/ELFWriter.h Mon Jul 13 17:40:39 2009
@@ -218,7 +218,8 @@
     }
 
     // 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 @@
     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);





More information about the llvm-commits mailing list