[llvm-commits] [llvm] r76540 - in /llvm/trunk/lib: CodeGen/ELFCodeEmitter.cpp CodeGen/ELFWriter.cpp CodeGen/ELFWriter.h Target/X86/X86ELFWriterInfo.cpp

Bruno Cardoso Lopes bruno.cardoso at gmail.com
Mon Jul 20 23:51:32 PDT 2009


Author: bruno
Date: Tue Jul 21 01:51:32 2009
New Revision: 76540

URL: http://llvm.org/viewvc/llvm-project?rev=76540&view=rev
Log:
Support adding relocations for data sections, handling the cases where
global declared symbols are initialized with references from other global
symbols.

Modified:
    llvm/trunk/lib/CodeGen/ELFCodeEmitter.cpp
    llvm/trunk/lib/CodeGen/ELFWriter.cpp
    llvm/trunk/lib/CodeGen/ELFWriter.h
    llvm/trunk/lib/Target/X86/X86ELFWriterInfo.cpp

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

==============================================================================
--- llvm/trunk/lib/CodeGen/ELFCodeEmitter.cpp (original)
+++ llvm/trunk/lib/CodeGen/ELFCodeEmitter.cpp Tue Jul 21 01:51:32 2009
@@ -68,6 +68,10 @@
   FnSym->SectionIdx = ES->SectionIdx;
   FnSym->Size = ES->getCurrentPCOffset()-FnStartOff;
 
+  // keep track of the emitted function leaving its symbol index as zero
+  // to be patched up later when emitting the symbol table
+  EW.setGlobalSymLookup(F, 0);
+
   // Offset from start of Section
   FnSym->Value = FnStartOff;
 

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

==============================================================================
--- llvm/trunk/lib/CodeGen/ELFWriter.cpp (original)
+++ llvm/trunk/lib/CodeGen/ELFWriter.cpp Tue Jul 21 01:51:32 2009
@@ -240,30 +240,31 @@
 
 // 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());
+static bool isELFBssSym(const GlobalVariable *GV) {
+  const Constant *CV = GV->getInitializer();
+  return ((CV->isNullValue() || isa<UndefValue>(CV)) && !GV->isWeakForLinker());
 }
 
 // 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());
+static bool isELFCommonSym(const GlobalVariable *GV) {
+  const Constant *CV = GV->getInitializer();
+  return ((CV->isNullValue() || isa<UndefValue>(CV)) && 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)));
+static bool isELFDataSym(const Constant *CV) {
+  return (!(CV->isNullValue() || isa<UndefValue>(CV)));
 }
 
 // EmitGlobal - Choose the right section for global and emit it
 void ELFWriter::EmitGlobal(const GlobalValue *GV) {
 
+  // Check if the referenced symbol is already emitted
+  if (GblSymLookup.find(GV) != GblSymLookup.end())
+    return;
+
   // Handle ELF Bind, Visibility and Type for the current symbol
   unsigned SymBind = getGlobalELFBinding(GV);
   ELFSym *GblSym = new ELFSym(GV);
@@ -287,7 +288,7 @@
     unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType());
     GblSym->Size = Size;
 
-    if (isELFCommonSym(GV)) {
+    if (isELFCommonSym(GVar)) {
       GblSym->SectionIdx = ELFSection::SHN_COMMON;
       getSection(S->getName(), ELFSection::SHT_NOBITS, SectionFlags, 1);
 
@@ -296,7 +297,7 @@
       // value contains its alignment.
       GblSym->Value = Align;
 
-    } else if (isELFBssSym(GV)) {
+    } else if (isELFBssSym(GVar)) {
       ELFSection &ES =
         getSection(S->getName(), ELFSection::SHT_NOBITS, SectionFlags);
       GblSym->SectionIdx = ES.SectionIdx;
@@ -336,7 +337,7 @@
     SymbolList.push_back(GblSym);
   }
 
-  GblSymLookup[GV] = SymIdx;
+  setGlobalSymLookup(GV, SymIdx);
 }
 
 void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
@@ -410,8 +411,37 @@
     for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I)
       EmitGlobalConstant(CP->getOperand(I), GblS);
     return;
+  } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
+    // This is a constant address for a global variable or function and
+    // therefore must be referenced using a relocation entry.
+
+    // Check if the referenced symbol is already emitted
+    if (GblSymLookup.find(GV) == GblSymLookup.end())
+      EmitGlobal(GV);
+
+    // Create the relocation entry for the global value
+    MachineRelocation MR =
+      MachineRelocation::getGV(GblS.getCurrentPCOffset(),
+                               TEW->getAbsoluteLabelMachineRelTy(),
+                               const_cast<GlobalValue*>(GV));
+
+    // Fill the data entry with zeros
+    for (unsigned i=0; i < Size; ++i)
+      GblS.emitByte(0);
+
+    // Add the relocation entry for the current data section
+    GblS.addRelocation(MR);
+    return;
+  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
+    if (CE->getOpcode() == Instruction::BitCast) {
+      EmitGlobalConstant(CE->getOperand(0), GblS);
+      return;
+    }
+    // See AsmPrinter::EmitConstantValueOnly for other ConstantExpr types
+    llvm_unreachable("Unsupported ConstantExpr type");
   }
-  llvm_unreachable("unknown global constant");
+
+  llvm_unreachable("Unknown global constant type");
 }
 
 
@@ -431,19 +461,13 @@
 
   // Build and emit data, bss and "common" sections.
   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
-       I != E; ++I) {
+       I != E; ++I)
     EmitGlobal(I);
-  }
 
   // Emit all pending globals
-  // TODO: this should be done only for referenced symbols
   for (SetVector<GlobalValue*>::const_iterator I = PendingGlobals.begin(),
-       E = PendingGlobals.end(); I != E; ++I) {
-    // No need to emit the symbol again
-    if (GblSymLookup.find(*I) != GblSymLookup.end())
-      continue;
+       E = PendingGlobals.end(); I != E; ++I)
     EmitGlobal(*I);
-  }
 
   // Emit non-executable stack note
   if (TAI->getNonexecutableStackDirective())
@@ -731,7 +755,7 @@
     EmitSymbol(SymTab, Sym);
 
     // Record the symbol table index for each global value
-    if (Sym.GV) GblSymLookup[Sym.GV] = i;
+    if (Sym.GV) setGlobalSymLookup(Sym.GV, i);
 
     // Keep track on the symbol index into the symbol table
     Sym.SymTabIdx = i;

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

==============================================================================
--- llvm/trunk/lib/CodeGen/ELFWriter.h (original)
+++ llvm/trunk/lib/CodeGen/ELFWriter.h Tue Jul 21 01:51:32 2009
@@ -211,6 +211,11 @@
     unsigned getGlobalELFVisibility(const GlobalValue *GV);
     unsigned getElfSectionFlags(unsigned Flags);
 
+    // setGlobalSymLookup - Set global value 'GV' with 'Index' in the lookup map
+    void setGlobalSymLookup(const GlobalValue *GV, unsigned Index) {
+      GblSymLookup[GV] = Index;
+    }
+
     // 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
     // the offset in ELFHeader of these various pieces to update and other

Modified: llvm/trunk/lib/Target/X86/X86ELFWriterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ELFWriterInfo.cpp?rev=76540&r1=76539&r2=76540&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86ELFWriterInfo.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ELFWriterInfo.cpp Tue Jul 21 01:51:32 2009
@@ -64,7 +64,9 @@
   if (is64Bit) {
     switch(RelTy) {
     case R_X86_64_PC32: return -4;
-    case R_X86_64_32: return 0;
+    case R_X86_64_32:
+    case R_X86_64_64:
+      return 0;
     default:
       llvm_unreachable("unknown x86_64 relocation type");
     }





More information about the llvm-commits mailing list