Get closer to handling globals correctly. We now generally get them in the
authorNate Begeman <natebegeman@mac.com>
Fri, 25 Aug 2006 06:36:58 +0000 (06:36 +0000)
committerNate Begeman <natebegeman@mac.com>
Fri, 25 Aug 2006 06:36:58 +0000 (06:36 +0000)
right section.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29871 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/MachOWriter.h
lib/CodeGen/MachOWriter.cpp

index 36fc6169e78437592a3e41f3678612951ca4015b..6f0d9575a69f69495fff4c6975e865cc59b9c58c 100644 (file)
 #ifndef LLVM_CODEGEN_MACHOWRITER_H
 #define LLVM_CODEGEN_MACHOWRITER_H
 
-#include "llvm/CodeGen/MachineRelocation.h"
+#include "llvm/DerivedTypes.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
 #include <list>
 
 namespace llvm {
@@ -377,6 +379,31 @@ namespace llvm {
                         MachOSection::S_ATTR_PURE_INSTRUCTIONS |
                         MachOSection::S_ATTR_SOME_INSTRUCTIONS);
     }
+    MachOSection &getBSSSection() {
+      return getSection("__DATA", "__bss", MachOSection::S_ZEROFILL);
+    }
+    MachOSection &getDataSection() {
+      return getSection("__DATA", "__data");
+    }
+    MachOSection &getConstSection(const Type *Ty) {
+      // FIXME: support cstring literals and pointer literal
+      if (Ty->isPrimitiveType()) {
+        unsigned Size = TM.getTargetData()->getTypeSize(Ty);
+        switch(Size) {
+        default: break; // Fall through to __TEXT,__const
+        case 4:
+          return getSection("__TEXT", "__literal4",
+                            MachOSection::S_4BYTE_LITERALS);
+        case 8:
+          return getSection("__TEXT", "__literal8",
+                            MachOSection::S_8BYTE_LITERALS);
+        case 16:
+          return getSection("__TEXT", "__literal16",
+                            MachOSection::S_16BYTE_LITERALS);
+        }
+      }
+      return getSection("__TEXT", "__const");
+    }
     
     /// MachOSymTab - This struct contains information about the offsets and 
     /// size of symbol table information.
@@ -488,7 +515,8 @@ namespace llvm {
       static unsigned entrySize() { return 12; }
 
       MachOSym(const GlobalValue *gv, uint8_t sect) : GV(gv), n_strx(0), 
-        n_type(N_UNDF), n_sect(sect), n_desc(0), n_value(0) {}
+        n_type(sect == NO_SECT ? N_UNDF : N_SECT), n_sect(sect), n_desc(0),
+        n_value(0) {}
     };
 
     /// SymbolTable - This is the list of symbols we have emitted to the file.
@@ -496,6 +524,11 @@ namespace llvm {
     /// local symbols first in the list).
     std::vector<MachOSym> SymbolTable;
     
+    /// PendingSyms - This is a list of externally defined symbols that we have
+    /// been asked to emit, but have not seen a reference to.  When a reference
+    /// is seen, the symbol will move from this list to the SymbolTable.
+    std::vector<MachOSym> PendingSyms;
+    
     /// DynamicSymbolTable - This is just a vector of indices into
     /// SymbolTable to aid in emitting the DYSYMTAB load command.
     std::vector<unsigned> DynamicSymbolTable;
@@ -586,6 +619,7 @@ namespace llvm {
       
     }
   private:
+    void AddSymbolToSection(MachOSection &MOS, GlobalVariable *GV);
     void EmitGlobal(GlobalVariable *GV);
     void EmitHeaderAndLoadCommands();
     void EmitSections();
index e3228cb5c778ad97b1946c0e4cd4961573e18ef7..d9e3b880585ce5cd9cca49125b9d8568c43a5284 100644 (file)
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineRelocation.h"
 #include "llvm/CodeGen/MachOWriter.h"
-#include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetJITInfo.h"
-#include "llvm/Target/TargetMachine.h"
 #include "llvm/Support/Mangler.h"
+#include "llvm/Support/MathExtras.h"
 #include <iostream>
 using namespace llvm;
 
@@ -137,10 +136,9 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) {
     // appending linkage is illegal for functions.
     assert(0 && "Unknown linkage type!");
   case GlobalValue::ExternalLinkage:
-    FnSym.n_type = MachOWriter::MachOSym::N_SECT | MachOWriter::MachOSym::N_EXT;
+    FnSym.n_type |=  MachOWriter::MachOSym::N_EXT;
     break;
   case GlobalValue::InternalLinkage:
-    FnSym.n_type = MachOWriter::MachOSym::N_SECT;
     break;
   }
   
@@ -188,8 +186,75 @@ MachOWriter::~MachOWriter() {
   delete MCE;
 }
 
+void MachOWriter::AddSymbolToSection(MachOSection &Sec, GlobalVariable *GV) {
+  const Type *Ty = GV->getType()->getElementType();
+  unsigned Size = TM.getTargetData()->getTypeSize(Ty);
+  unsigned Align = Log2_32(TM.getTargetData()->getTypeAlignment(Ty));
+  
+  MachOSym Sym(GV, Sec.Index);
+  // Reserve space in the .bss section for this symbol while maintaining the
+  // desired section alignment, which must be at least as much as required by
+  // this symbol.
+  if (Align) {
+    Sec.align = std::max(Sec.align, Align);
+    Sec.size = (Sec.size + Align - 1) & ~(Align-1);
+  }
+  // Record the offset of the symbol, and then allocate space for it.
+  Sym.n_value = Sec.size;
+  Sec.size += Size;
+
+  switch (GV->getLinkage()) {
+  default:  // weak/linkonce handled above
+    assert(0 && "Unexpected linkage type!");
+  case GlobalValue::ExternalLinkage:
+    Sym.n_type |= MachOSym::N_EXT;
+    break;
+  case GlobalValue::InternalLinkage:
+    break;
+  }
+  SymbolTable.push_back(Sym);
+}
+
 void MachOWriter::EmitGlobal(GlobalVariable *GV) {
-  // FIXME: do something smart here.
+  const Type *Ty = GV->getType()->getElementType();
+  unsigned Size = TM.getTargetData()->getTypeSize(Ty);
+  bool NoInit = !GV->hasInitializer();
+
+  // If this global has a zero initializer, it is part of the .bss or common
+  // section.
+  if (NoInit || GV->getInitializer()->isNullValue()) {
+    // If this global is part of the common block, add it now.  Variables are
+    // part of the common block if they are zero initialized and allowed to be
+    // merged with other symbols.
+    if (NoInit || GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) {
+      MachOWriter::MachOSym ExtOrCommonSym(GV, MachOSym::NO_SECT);
+      ExtOrCommonSym.n_type |= MachOSym::N_EXT;
+      // For undefined (N_UNDF) external (N_EXT) types, n_value is the size in
+      // bytes of the symbol.
+      ExtOrCommonSym.n_value = Size;
+      // If the symbol is external, we'll put it on a list of symbols whose
+      // addition to the symbol table is being pended until we find a reference
+      if (NoInit)
+        PendingSyms.push_back(ExtOrCommonSym);
+      else
+        SymbolTable.push_back(ExtOrCommonSym);
+      return;
+    }
+    // Otherwise, this symbol is part of the .bss section.
+    MachOSection &BSS = getBSSSection();
+    AddSymbolToSection(BSS, GV);
+    return;
+  }
+  
+  // Scalar read-only data goes in a literal section if the scalar is 4, 8, or
+  // 16 bytes, or a cstring.  Other read only data goes into a regular const
+  // section.  Read-write data goes in the data section.
+  MachOSection &Sec = GV->isConstant() ? getConstSection(Ty) : getDataSection();
+  AddSymbolToSection(Sec, GV);
+  
+  // FIXME: actually write out the initializer to the section.  This will
+  // require ExecutionEngine's InitializeMemory() function, which will need to
+  // be enhanced to support relocations.
 }