[llvm-commits] [llvm] r80351 - in /llvm/trunk: include/llvm/MC/MCAssembler.h lib/MC/MCAssembler.cpp lib/MC/MCMachOStreamer.cpp test/MC/MachO/comm-1.s

Daniel Dunbar daniel at zuster.org
Fri Aug 28 00:08:36 PDT 2009


Author: ddunbar
Date: Fri Aug 28 02:08:35 2009
New Revision: 80351

URL: http://llvm.org/viewvc/llvm-project?rev=80351&view=rev
Log:
llvm-mc: Support .comm emission.

Added:
    llvm/trunk/test/MC/MachO/comm-1.s
Modified:
    llvm/trunk/include/llvm/MC/MCAssembler.h
    llvm/trunk/lib/MC/MCAssembler.cpp
    llvm/trunk/lib/MC/MCMachOStreamer.cpp

Modified: llvm/trunk/include/llvm/MC/MCAssembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAssembler.h?rev=80351&r1=80350&r2=80351&view=diff

==============================================================================
--- llvm/trunk/include/llvm/MC/MCAssembler.h (original)
+++ llvm/trunk/include/llvm/MC/MCAssembler.h Fri Aug 28 02:08:35 2009
@@ -452,6 +452,17 @@
   /// IsPrivateExtern - True if this symbol is private extern.
   unsigned IsPrivateExtern : 1;
 
+  /// CommonSize - The size of the symbol, if it is 'common', or 0.
+  //
+  // FIXME: Pack this in with other fields? We could put it in offset, since a
+  // common symbol can never get a definition.
+  uint64_t CommonSize;
+
+  /// CommonAlign - The alignment of the symbol, if it is 'common'.
+  //
+  // FIXME: Pack this in with other fields?
+  unsigned CommonAlign;
+
   /// Flags - The Flags field is used by object file implementations to store
   /// additional per symbol information which is not easily classified.
   uint32_t Flags;
@@ -485,7 +496,31 @@
   
   bool isPrivateExtern() const { return IsPrivateExtern; }
   void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
-  
+
+  /// isCommon - Is this a 'common' symbol.
+  bool isCommon() const { return CommonSize != 0; }
+
+  /// setCommon - Mark this symbol as being 'common'.
+  ///
+  /// \param Size - The size of the symbol.
+  /// \param Align - The alignment of the symbol.
+  void setCommon(uint64_t Size, unsigned Align) {
+    CommonSize = Size;
+    CommonAlign = Align;
+  }
+
+  /// getCommonSize - Return the size of a 'common' symbol.
+  uint64_t getCommonSize() const {
+    assert(isCommon() && "Not a 'common' symbol!");
+    return CommonSize;
+  }
+
+  /// getCommonAlignment - Return the alignment of a 'common' symbol.
+  unsigned getCommonAlignment() const {
+    assert(isCommon() && "Not a 'common' symbol!");
+    return CommonAlign;
+  }
+
   /// getFlags - Get the (implementation defined) symbol flags.
   uint32_t getFlags() const { return Flags; }
 

Modified: llvm/trunk/lib/MC/MCAssembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAssembler.cpp?rev=80351&r1=80350&r2=80351&view=diff

==============================================================================
--- llvm/trunk/lib/MC/MCAssembler.cpp (original)
+++ llvm/trunk/lib/MC/MCAssembler.cpp Fri Aug 28 02:08:35 2009
@@ -25,6 +25,11 @@
 
 STATISTIC(EmittedFragments, "Number of emitted assembler fragments");
 
+// FIXME FIXME FIXME: There are number of places in this file where we convert
+// what is a 64-bit assembler value used for computation into a value in the
+// object file, which may truncate it. We should detect that truncation where
+// invalid and report errors back.
+
 static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
                           MachObjectWriter &MOW);
 
@@ -328,6 +333,8 @@
     MCSymbolData &Data = *MSD.SymbolData;
     MCSymbol &Symbol = Data.getSymbol();
     uint8_t Type = 0;
+    uint16_t Flags = Data.getFlags();
+    uint32_t Address = 0;
 
     // Set the N_TYPE bits. See <mach-o/nlist.h>.
     //
@@ -348,6 +355,30 @@
     if (Data.isExternal() || Symbol.isUndefined())
       Type |= STF_External;
 
+    // Compute the symbol address.
+    if (Symbol.isDefined()) {
+      if (Symbol.isAbsolute()) {
+        llvm_unreachable("FIXME: Not yet implemented!");
+      } else {
+        Address = Data.getFragment()->getAddress() + Data.getOffset();
+      }
+    } else if (Data.isCommon()) {
+      // Common symbols are encoded with the size in the address
+      // field, and their alignment in the flags.
+      Address = Data.getCommonSize();
+
+      // Common alignment is packed into the 'desc' bits.
+      if (unsigned Align = Data.getCommonAlignment()) {
+        unsigned Log2Size = Log2_32(Align);
+        assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
+        if (Log2Size > 15)
+          llvm_report_error("invalid 'common' alignment '" +
+                            Twine(Align) + "'");
+        // FIXME: Keep this mask with the SymbolFlags enumeration.
+        Flags = (Flags & 0xF0FF) | (Log2Size << 8);
+      }
+    }
+
     // struct nlist (12 bytes)
 
     Write32(MSD.StringIndex);
@@ -356,17 +387,7 @@
     
     // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
     // value.
-    Write16(Data.getFlags() & 0xFFFF);
-
-    // Write the symbol address.
-    uint32_t Address = 0;
-    if (Symbol.isDefined()) {
-      if (Symbol.isAbsolute()) {
-        llvm_unreachable("FIXME: Not yet implemented!");
-      } else {
-        Address = Data.getFragment()->getAddress() + Data.getOffset();
-      }
-    }
+    Write16(Flags);
     Write32(Address);
   }
 
@@ -910,7 +931,8 @@
 MCSymbolData::MCSymbolData(MCSymbol &_Symbol, MCFragment *_Fragment,
                            uint64_t _Offset, MCAssembler *A)
   : Symbol(_Symbol), Fragment(_Fragment), Offset(_Offset),
-    IsExternal(false), IsPrivateExtern(false), Flags(0), Index(0)
+    IsExternal(false), IsPrivateExtern(false),
+    CommonSize(0), CommonAlign(0), Flags(0), Index(0)
 {
   if (A)
     A->getSymbolList().push_back(this);

Modified: llvm/trunk/lib/MC/MCMachOStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCMachOStreamer.cpp?rev=80351&r1=80350&r2=80351&view=diff

==============================================================================
--- llvm/trunk/lib/MC/MCMachOStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCMachOStreamer.cpp Fri Aug 28 02:08:35 2009
@@ -224,7 +224,7 @@
     break;
 
   case MCStreamer::Global:
-    getSymbolData(*Symbol).setExternal(true);
+    SD.setExternal(true);
     break;
 
   case MCStreamer::LazyReference:
@@ -273,7 +273,12 @@
 
 void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
                                        unsigned Pow2Alignment) {
-  llvm_unreachable("FIXME: Not yet implemented!");
+  // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.
+  assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
+
+  MCSymbolData &SD = getSymbolData(*Symbol);
+  SD.setExternal(true);
+  SD.setCommon(Size, 1 << Pow2Alignment);
 }
 
 void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,

Added: llvm/trunk/test/MC/MachO/comm-1.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/comm-1.s?rev=80351&view=auto

==============================================================================
--- llvm/trunk/test/MC/MachO/comm-1.s (added)
+++ llvm/trunk/test/MC/MachO/comm-1.s Fri Aug 28 02:08:35 2009
@@ -0,0 +1,114 @@
+// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump | FileCheck %s
+
+        .comm           sym_comm_B, 2
+        .comm           sym_comm_A, 4
+        .comm           sym_comm_C, 8, 2
+        .comm           sym_comm_D, 2, 3
+
+        .no_dead_strip sym_comm_C
+
+// CHECK: ('cputype', 7)
+// CHECK: ('cpusubtype', 3)
+// CHECK: ('filetype', 1)
+// CHECK: ('num_load_commands', 1)
+// CHECK: ('load_commands_size', 228)
+// CHECK: ('flag', 0)
+// CHECK: ('load_commands', [
+// CHECK:   # Load Command 0
+// CHECK:  (('command', 1)
+// CHECK:   ('size', 124)
+// CHECK:   ('segment_name', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK:   ('vm_addr', 0)
+// CHECK:   ('vm_size', 0)
+// CHECK:   ('file_offset', 256)
+// CHECK:   ('file_size', 0)
+// CHECK:   ('maxprot', 7)
+// CHECK:   ('initprot', 7)
+// CHECK:   ('num_sections', 1)
+// CHECK:   ('flags', 0)
+// CHECK:   ('sections', [
+// CHECK:     # Section 0
+// CHECK:    (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK:     ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK:     ('address', 0)
+// CHECK:     ('size', 0)
+// CHECK:     ('offset', 256)
+// CHECK:     ('alignment', 0)
+// CHECK:     ('reloc_offset', 0)
+// CHECK:     ('num_reloc', 0)
+// CHECK:     ('flags', 0x80000000)
+// CHECK:     ('reserved1', 0)
+// CHECK:     ('reserved2', 0)
+// CHECK:    ),
+// CHECK:   ('_relocations', [
+// CHECK:   ])
+// CHECK:   ])
+// CHECK:  ),
+// CHECK:   # Load Command 1
+// CHECK:  (('command', 2)
+// CHECK:   ('size', 24)
+// CHECK:   ('symoff', 256)
+// CHECK:   ('nsyms', 4)
+// CHECK:   ('stroff', 304)
+// CHECK:   ('strsize', 48)
+// CHECK:   ('_string_data', '\x00sym_comm_B\x00sym_comm_A\x00sym_comm_C\x00sym_comm_D\x00\x00\x00\x00')
+// CHECK:   ('_symbols', [
+// CHECK:     # Symbol 0
+// CHECK:    (('n_strx', 12)
+// CHECK:     ('n_type', 0x1)
+// CHECK:     ('n_sect', 0)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 4)
+// CHECK:     ('_string', 'sym_comm_A')
+// CHECK:    ),
+// CHECK:     # Symbol 1
+// CHECK:    (('n_strx', 1)
+// CHECK:     ('n_type', 0x1)
+// CHECK:     ('n_sect', 0)
+// CHECK:     ('n_desc', 0)
+// CHECK:     ('n_value', 2)
+// CHECK:     ('_string', 'sym_comm_B')
+// CHECK:    ),
+// CHECK:     # Symbol 2
+// CHECK:    (('n_strx', 23)
+// CHECK:     ('n_type', 0x1)
+// CHECK:     ('n_sect', 0)
+// CHECK:     ('n_desc', 544)
+// CHECK:     ('n_value', 8)
+// CHECK:     ('_string', 'sym_comm_C')
+// CHECK:    ),
+// CHECK:     # Symbol 3
+// CHECK:    (('n_strx', 34)
+// CHECK:     ('n_type', 0x1)
+// CHECK:     ('n_sect', 0)
+// CHECK:     ('n_desc', 768)
+// CHECK:     ('n_value', 2)
+// CHECK:     ('_string', 'sym_comm_D')
+// CHECK:    ),
+// CHECK:   ])
+// CHECK:  ),
+// CHECK:   # Load Command 2
+// CHECK:  (('command', 11)
+// CHECK:   ('size', 80)
+// CHECK:   ('ilocalsym', 0)
+// CHECK:   ('nlocalsym', 0)
+// CHECK:   ('iextdefsym', 0)
+// CHECK:   ('nextdefsym', 0)
+// CHECK:   ('iundefsym', 0)
+// CHECK:   ('nundefsym', 4)
+// CHECK:   ('tocoff', 0)
+// CHECK:   ('ntoc', 0)
+// CHECK:   ('modtaboff', 0)
+// CHECK:   ('nmodtab', 0)
+// CHECK:   ('extrefsymoff', 0)
+// CHECK:   ('nextrefsyms', 0)
+// CHECK:   ('indirectsymoff', 0)
+// CHECK:   ('nindirectsyms', 0)
+// CHECK:   ('extreloff', 0)
+// CHECK:   ('nextrel', 0)
+// CHECK:   ('locreloff', 0)
+// CHECK:   ('nlocrel', 0)
+// CHECK:   ('_indirect_symbols', [
+// CHECK:   ])
+// CHECK:  ),
+// CHECK: ])





More information about the llvm-commits mailing list