OSDN Git Service

Sorry for such a large commit. The summary is that only MachO cares about the
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 7 Dec 2010 00:27:36 +0000 (00:27 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 7 Dec 2010 00:27:36 +0000 (00:27 +0000)
actuall addresses in a .o file, so it is better to let the MachO writer compute
it.

This is good for two reasons. First, areas that shouldn't care about
addresses now don't have access to it. Second, the layout of each section
is independent. I should use this in a subsequent commit to speed it up.

Most of the patch is just removing the section address computation. The two
interesting parts are the change on how we handle padding in the end
of sections and how MachO can get the address of a-b when a and b are in
different sections.

Since now the expression evaluation normally doesn't know the section address,
it will think that a-b needs relocation and let the MachO writer know. Once
it has computed the section addresses, it calls back the expression evaluation
with the section addresses to resolve these expressions.

The remaining problem is the handling of padding. Currently it will create
a special alignment fragment at the end. Since that fragment doesn't update
the alignment of the section, it needs the real address to be computed.

Since now the layout will not compute a-b with a and b in different sections,
the only effect that the special alignment fragment has is update the
address size of the section. This can also be done by the MachO writer.

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

15 files changed:
include/llvm/MC/MCAsmLayout.h
include/llvm/MC/MCAssembler.h
include/llvm/MC/MCExpr.h
include/llvm/MC/MCObjectStreamer.h
include/llvm/MC/MCObjectWriter.h
lib/MC/ELFObjectWriter.cpp
lib/MC/MCAssembler.cpp
lib/MC/MCELFStreamer.cpp
lib/MC/MCExpr.cpp
lib/MC/MCMachOStreamer.cpp
lib/MC/MCObjectStreamer.cpp
lib/MC/MCPureStreamer.cpp
lib/MC/MachObjectWriter.cpp
lib/MC/WinCOFFObjectWriter.cpp
lib/MC/WinCOFFStreamer.cpp

index ce9692d..805af62 100644 (file)
@@ -66,11 +66,6 @@ public:
   /// been initialized.
   void LayoutFragment(MCFragment *Fragment);
 
-  /// \brief Performs initial layout for a single section, assuming that the
-  /// previous section (including its fragments) has already been layed out
-  /// correctly.
-  void LayoutSection(MCSectionData *SD);
-
   /// @name Section Access (in layout order)
   /// @{
 
@@ -93,20 +88,9 @@ public:
   uint64_t getFragmentOffset(const MCFragment *F) const;
 
   /// @}
-  /// @name Section Layout Data
-  /// @{
-
-  /// \brief Get the computed address of the given section.
-  uint64_t getSectionAddress(const MCSectionData *SD) const;
-
-  /// @}
   /// @name Utility Functions
   /// @{
 
-  /// \brief Get the address of the given fragment, as computed in the current
-  /// layout.
-  uint64_t getFragmentAddress(const MCFragment *F) const;
-
   /// \brief Get the address space size of the given section, as it effects
   /// layout. This may differ from the size reported by \see getSectionSize() by
   /// not including section tail padding.
@@ -116,13 +100,6 @@ public:
   /// file. This may include additional padding, or be 0 for virtual sections.
   uint64_t getSectionFileSize(const MCSectionData *SD) const;
 
-  /// \brief Get the logical data size of the given section.
-  uint64_t getSectionSize(const MCSectionData *SD) const;
-
-  /// \brief Get the address of the given symbol, as computed in the current
-  /// layout.
-  uint64_t getSymbolAddress(const MCSymbolData *SD) const;
-
   /// \brief Get the offset of the given symbol, as computed in the current
   /// layout.
   uint64_t getSymbolOffset(const MCSymbolData *SD) const;
index ba89436..8a5009f 100644 (file)
@@ -236,19 +236,12 @@ class MCAlignFragment : public MCFragment {
   /// target dependent.
   bool EmitNops : 1;
 
-  /// OnlyAlignAddress - Flag to indicate that this align is only used to adjust
-  /// the address space size of a section and that it should not be included as
-  /// part of the section size. This flag can only be used on the last fragment
-  /// in a section.
-  bool OnlyAlignAddress : 1;
-
 public:
   MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize,
                   unsigned _MaxBytesToEmit, MCSectionData *SD = 0)
     : MCFragment(FT_Align, SD), Alignment(_Alignment),
       Value(_Value),ValueSize(_ValueSize),
-      MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false),
-      OnlyAlignAddress(false) {}
+      MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {}
 
   /// @name Accessors
   /// @{
@@ -264,9 +257,6 @@ public:
   bool hasEmitNops() const { return EmitNops; }
   void setEmitNops(bool Value) { EmitNops = Value; }
 
-  bool hasOnlyAlignAddress() const { return OnlyAlignAddress; }
-  void setOnlyAlignAddress(bool Value) { OnlyAlignAddress = Value; }
-
   /// @}
 
   static bool classof(const MCFragment *F) {
@@ -447,10 +437,6 @@ private:
   //
   // FIXME: This could all be kept private to the assembler implementation.
 
-  /// Address - The computed address of this section. This is ~0 until
-  /// initialized.
-  uint64_t Address;
-
   /// HasInstructions - Whether this section has had instructions emitted into
   /// it.
   unsigned HasInstructions : 1;
@@ -679,7 +665,6 @@ private:
 
   unsigned RelaxAll : 1;
   unsigned SubsectionsViaSymbols : 1;
-  unsigned PadSectionToAlignment : 1;
 
 private:
   /// Evaluate a fixup to a relocatable expression and the value which should be
@@ -713,7 +698,6 @@ private:
   /// Compute the effective fragment size assuming it is layed out at the given
   /// \arg SectionAddress and \arg FragmentOffset.
   uint64_t ComputeFragmentSize(const MCFragment &F,
-                               uint64_t SectionAddress,
                                uint64_t FragmentOffset) const;
 
   /// LayoutOnce - Perform one layout iteration and return true if any offsets
@@ -765,8 +749,7 @@ public:
   // option is to make this abstract, and have targets provide concrete
   // implementations as we do with AsmParser.
   MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
-              MCCodeEmitter &_Emitter, bool _PadSectionToAlignment,
-              raw_ostream &OS);
+              MCCodeEmitter &_Emitter, raw_ostream &OS);
   ~MCAssembler();
 
   MCContext &getContext() const { return Context; }
index 888934e..da3cebe 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef LLVM_MC_MCEXPR_H
 #define LLVM_MC_MCEXPR_H
 
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/DataTypes.h"
 
@@ -18,10 +19,12 @@ class MCAsmInfo;
 class MCAsmLayout;
 class MCAssembler;
 class MCContext;
+class MCSectionData;
 class MCSymbol;
 class MCValue;
 class raw_ostream;
 class StringRef;
+typedef DenseMap<const MCSectionData*, uint64_t> SectionAddrMap;
 
 /// MCExpr - Base class for the full range of assembler expressions which are
 /// needed for parsing.
@@ -42,12 +45,14 @@ private:
   void operator=(const MCExpr&); // DO NOT IMPLEMENT
 
   bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
-                          const MCAsmLayout *Layout) const;
+                          const MCAsmLayout *Layout,
+                          const SectionAddrMap *Addrs) const;
 protected:
   explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {}
 
   bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
                                  const MCAsmLayout *Layout,
+                                 const SectionAddrMap *Addrs,
                                  bool InSet) const;
 public:
   /// @name Accessors
@@ -76,6 +81,8 @@ public:
   bool EvaluateAsAbsolute(int64_t &Res) const;
   bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const;
   bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
+  bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout,
+                          const SectionAddrMap &Addrs) const;
 
   /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable
   /// value, i.e. an expression of the fixed form (a - b + constant).
index d130ba4..c6dd960 100644 (file)
@@ -37,8 +37,7 @@ class MCObjectStreamer : public MCStreamer {
 
 protected:
   MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB,
-                   raw_ostream &_OS, MCCodeEmitter *_Emitter,
-                   bool _PadSectionToAlignment);
+                   raw_ostream &_OS, MCCodeEmitter *_Emitter);
   ~MCObjectStreamer();
 
   MCSectionData *getCurrentSectionData() const {
index 90fe6e8..b819a57 100644 (file)
@@ -62,7 +62,8 @@ public:
   ///
   /// This routine is called by the assembler after layout and relaxation is
   /// complete.
-  virtual void ExecutePostLayoutBinding(MCAssembler &Asm) = 0;
+  virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
+                                        const MCAsmLayout &Layout) = 0;
 
   /// Record a relocation entry.
   ///
index 4daab49..b51e508 100644 (file)
@@ -325,7 +325,8 @@ namespace {
     virtual void CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout,
                              GroupMapTy &GroupMap, RevGroupMapTy &RevGroupMap);
 
-    virtual void ExecutePostLayoutBinding(MCAssembler &Asm);
+    virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
+                                          const MCAsmLayout &Layout);
 
     virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
                           uint64_t Address, uint64_t Offset,
@@ -557,7 +558,8 @@ static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) {
   return 0;
 }
 
-void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
+void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
+                                               const MCAsmLayout &Layout) {
   // The presence of symbol versions causes undefined symbols and
   // versions declared with @@@ to be renamed.
 
@@ -1365,11 +1367,11 @@ static uint64_t GetSectionFileSize(const MCAsmLayout &Layout,
   return Layout.getSectionFileSize(&SD);
 }
 
-static uint64_t GetSectionSize(const MCAsmLayout &Layout,
-                                   const MCSectionData &SD) {
+static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout,
+                                      const MCSectionData &SD) {
   if (IsELFMetaDataSection(SD))
     return DataSectionSize(SD);
-  return Layout.getSectionSize(&SD);
+  return Layout.getSectionAddressSize(&SD);
 }
 
 static void WriteDataSectionData(ELFObjectWriter *W, const MCSectionData &SD) {
@@ -1479,7 +1481,7 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
     else
       GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, GroupMap[&Section]);
 
-    uint64_t Size = GetSectionSize(Layout, SD);
+    uint64_t Size = GetSectionAddressSize(Layout, SD);
 
     WriteSection(Asm, SectionIndexMap, GroupSymbolIndex,
                  SectionOffsetMap[&Section], Size,
index 299eb0a..4f63a08 100644 (file)
@@ -38,7 +38,6 @@ STATISTIC(FragmentLayouts, "Number of fragment layouts");
 STATISTIC(ObjectBytes, "Number of emitted object file bytes");
 STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps");
 STATISTIC(RelaxedInstructions, "Number of relaxed instructions");
-STATISTIC(SectionLayouts, "Number of section layouts");
 }
 }
 
@@ -113,11 +112,6 @@ void MCAsmLayout::EnsureValid(const MCFragment *F) const {
   }
 }
 
-uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const {
-  assert(F->getParent() && "Missing section()!");
-  return getSectionAddress(F->getParent()) + getFragmentOffset(F);
-}
-
 uint64_t MCAsmLayout::getFragmentEffectiveSize(const MCFragment *F) const {
   EnsureValid(F);
   assert(F->EffectiveSize != ~UINT64_C(0) && "Address not set!");
@@ -135,17 +129,6 @@ uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const {
   return getFragmentOffset(SD->getFragment()) + SD->getOffset();
 }
 
-uint64_t MCAsmLayout::getSymbolAddress(const MCSymbolData *SD) const {
-  assert(SD->getFragment() && "Invalid getAddress() on undefined symbol!");
-  return getFragmentAddress(SD->getFragment()) + SD->getOffset();
-}
-
-uint64_t MCAsmLayout::getSectionAddress(const MCSectionData *SD) const {
-  EnsureValid(SD->begin());
-  assert(SD->Address != ~UINT64_C(0) && "Address not set!");
-  return SD->Address;
-}
-
 uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {
   // The size is the last fragment's end offset.
   const MCFragment &F = SD->getFragmentList().back();
@@ -161,17 +144,6 @@ uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const {
   return getSectionAddressSize(SD);
 }
 
-uint64_t MCAsmLayout::getSectionSize(const MCSectionData *SD) const {
-  // The logical size is the address space size minus any tail padding.
-  uint64_t Size = getSectionAddressSize(SD);
-  const MCAlignFragment *AF =
-    dyn_cast<MCAlignFragment>(&(SD->getFragmentList().back()));
-  if (AF && AF->hasOnlyAlignAddress())
-    Size -= getFragmentEffectiveSize(AF);
-
-  return Size;
-}
-
 /* *** */
 
 MCFragment::MCFragment() : Kind(FragmentType(~0)) {
@@ -196,7 +168,6 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
   : Section(&_Section),
     Ordinal(~UINT32_C(0)),
     Alignment(1),
-    Address(~UINT64_C(0)),
     HasInstructions(false)
 {
   if (A)
@@ -221,11 +192,9 @@ MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment,
 /* *** */
 
 MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
-                         MCCodeEmitter &_Emitter, bool _PadSectionToAlignment,
-                         raw_ostream &_OS)
+                         MCCodeEmitter &_Emitter, raw_ostream &_OS)
   : Context(_Context), Backend(_Backend), Emitter(_Emitter),
-    OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false),
-    PadSectionToAlignment(_PadSectionToAlignment)
+    OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false)
 {
 }
 
@@ -285,14 +254,14 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
   if (const MCSymbolRefExpr *A = Target.getSymA()) {
     const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
     if (Sym.isDefined())
-      Value += Layout.getSymbolAddress(&getSymbolData(Sym));
+      Value += Layout.getSymbolOffset(&getSymbolData(Sym));
     else
       IsResolved = false;
   }
   if (const MCSymbolRefExpr *B = Target.getSymB()) {
     const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
     if (Sym.isDefined())
-      Value -= Layout.getSymbolAddress(&getSymbolData(Sym));
+      Value -= Layout.getSymbolOffset(&getSymbolData(Sym));
     else
       IsResolved = false;
   }
@@ -301,13 +270,12 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
     IsResolved = Writer.IsFixupFullyResolved(*this, Target, IsPCRel, DF);
 
   if (IsPCRel)
-    Value -= Layout.getFragmentAddress(DF) + Fixup.getOffset();
+    Value -= Layout.getFragmentOffset(DF) + Fixup.getOffset();
 
   return IsResolved;
 }
 
 uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
-                                          uint64_t SectionAddress,
                                           uint64_t FragmentOffset) const {
   switch (F.getKind()) {
   case MCFragment::FT_Data:
@@ -323,11 +291,7 @@ uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
   case MCFragment::FT_Align: {
     const MCAlignFragment &AF = cast<MCAlignFragment>(F);
 
-    assert((!AF.hasOnlyAlignAddress() || !AF.getNextNode()) &&
-           "Invalid OnlyAlignAddress bit, not the last fragment!");
-
-    uint64_t Size = OffsetToAlignment(SectionAddress + FragmentOffset,
-                                      AF.getAlignment());
+    uint64_t Size = OffsetToAlignment(FragmentOffset, AF.getAlignment());
 
     // Honor MaxBytesToEmit.
     if (Size > AF.getMaxBytesToEmit())
@@ -351,8 +315,6 @@ void MCAsmLayout::LayoutFile() {
   // Initialize the first section and set the valid fragment layout point. All
   // actual layout computations are done lazily.
   LastValidFragment = 0;
-  if (!getSectionOrder().empty())
-    getSectionOrder().front()->Address = 0;
 }
 
 void MCAsmLayout::LayoutFragment(MCFragment *F) {
@@ -371,43 +333,14 @@ void MCAsmLayout::LayoutFragment(MCFragment *F) {
 
   ++stats::FragmentLayouts;
 
-  // Compute the fragment start address.
-  uint64_t StartAddress = F->getParent()->Address;
-  uint64_t Address = StartAddress;
+  // Compute fragment offset and size.
+  uint64_t Offset = 0;
   if (Prev)
-    Address += Prev->Offset + Prev->EffectiveSize;
+    Offset += Prev->Offset + Prev->EffectiveSize;
 
-  // Compute fragment offset and size.
-  F->Offset = Address - StartAddress;
-  F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, StartAddress,
-                                                        F->Offset);
+  F->Offset = Offset;
+  F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, F->Offset);
   LastValidFragment = F;
-
-  // If this is the last fragment in a section, update the next section address.
-  if (!F->getNextNode()) {
-    unsigned NextIndex = F->getParent()->getLayoutOrder() + 1;
-    if (NextIndex != getSectionOrder().size())
-      LayoutSection(getSectionOrder()[NextIndex]);
-  }
-}
-
-void MCAsmLayout::LayoutSection(MCSectionData *SD) {
-  unsigned SectionOrderIndex = SD->getLayoutOrder();
-
-  ++stats::SectionLayouts;
-
-  // Compute the section start address.
-  uint64_t StartAddress = 0;
-  if (SectionOrderIndex) {
-    MCSectionData *Prev = getSectionOrder()[SectionOrderIndex - 1];
-    StartAddress = getSectionAddress(Prev) + getSectionAddressSize(Prev);
-  }
-
-  // Honor the section alignment requirements.
-  StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment());
-
-  // Set the section address.
-  SD->Address = StartAddress;
 }
 
 /// WriteFragmentData - Write the \arg F data to the output file.
@@ -566,7 +499,7 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD,
          ie = SD->end(); it != ie; ++it)
     WriteFragmentData(*this, Layout, *it, OW);
 
-  assert(OW->getStream().tell() - Start == Layout.getSectionFileSize(SD));
+  assert(OW->getStream().tell() - Start == Layout.getSectionAddressSize(SD));
 }
 
 
@@ -594,29 +527,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
   // Create the layout object.
   MCAsmLayout Layout(*this);
 
-  // Insert additional align fragments for concrete sections to explicitly pad
-  // the previous section to match their alignment requirements. This is for
-  // 'gas' compatibility, it shouldn't strictly be necessary.
-  if (PadSectionToAlignment) {
-    for (unsigned i = 1, e = Layout.getSectionOrder().size(); i < e; ++i) {
-      MCSectionData *SD = Layout.getSectionOrder()[i];
-
-      // Ignore sections without alignment requirements.
-      unsigned Align = SD->getAlignment();
-      if (Align <= 1)
-        continue;
-
-      // Ignore virtual sections, they don't cause file size modifications.
-      if (SD->getSection().isVirtualSection())
-        continue;
-
-      // Otherwise, create a new align fragment at the end of the previous
-      // section.
-      MCAlignFragment *AF = new MCAlignFragment(Align, 0, 1, Align,
-                                                Layout.getSectionOrder()[i - 1]);
-      AF->setOnlyAlignAddress(true);
-    }
-  }
+
 
   // Create dummy fragments and assign section ordinals.
   unsigned SectionIndex = 0;
@@ -668,7 +579,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
 
   // Allow the object writer a chance to perform post-layout binding (for
   // example, to set the index fields in the symbol data).
-  Writer->ExecutePostLayoutBinding(*this);
+  Writer->ExecutePostLayoutBinding(*this, Layout);
 
   // Evaluate and apply the fixups, generating relocation entries as necessary.
   for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) {
@@ -920,8 +831,6 @@ void MCFragment::dump() {
     const MCAlignFragment *AF = cast<MCAlignFragment>(this);
     if (AF->hasEmitNops())
       OS << " (emit nops)";
-    if (AF->hasOnlyAlignAddress())
-      OS << " (only align section)";
     OS << "\n       ";
     OS << " Alignment:" << AF->getAlignment()
        << " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize()
@@ -991,8 +900,7 @@ void MCSectionData::dump() {
   raw_ostream &OS = llvm::errs();
 
   OS << "<MCSectionData";
-  OS << " Alignment:" << getAlignment() << " Address:" << Address
-     << " Fragments:[\n      ";
+  OS << " Alignment:" << getAlignment() << " Fragments:[\n      ";
   for (iterator it = begin(), ie = end(); it != ie; ++it) {
     if (it != begin()) OS << ",\n      ";
     it->dump();
index f18c420..18d8fa3 100644 (file)
@@ -71,7 +71,7 @@ class MCELFStreamer : public MCObjectStreamer {
 public:
   MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
                   raw_ostream &OS, MCCodeEmitter *Emitter)
-    : MCObjectStreamer(Context, TAB, OS, Emitter, false) {}
+    : MCObjectStreamer(Context, TAB, OS, Emitter) {}
 
   ~MCELFStreamer() {}
 
index b4712c2..756e759 100644 (file)
@@ -238,20 +238,27 @@ void MCTargetExpr::Anchor() {}
 /* *** */
 
 bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const {
-  return EvaluateAsAbsolute(Res, 0, 0);
+  return EvaluateAsAbsolute(Res, 0, 0, 0);
 }
 
 bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
                                 const MCAsmLayout &Layout) const {
-  return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout);
+  return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0);
+}
+
+bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
+                                const MCAsmLayout &Layout,
+                                const SectionAddrMap &Addrs) const {
+  return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs);
 }
 
 bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
-  return EvaluateAsAbsolute(Res, &Asm, 0);
+  return EvaluateAsAbsolute(Res, &Asm, 0, 0);
 }
 
 bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
-                                const MCAsmLayout *Layout) const {
+                                const MCAsmLayout *Layout,
+                                const SectionAddrMap *Addrs) const {
   MCValue Value;
 
   // Fast path constants.
@@ -260,7 +267,7 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
     return true;
   }
 
-  if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, false) ||
+  if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, Addrs) ||
       !Value.isAbsolute()) {
     // EvaluateAsAbsolute is defined to return the "current value" of
     // the expression if we are given a Layout object, even in cases
@@ -268,11 +275,11 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
     if (Layout) {
       Res = Value.getConstant();
       if (Value.getSymA()) {
-       Res += Layout->getSymbolAddress(
+       Res += Layout->getSymbolOffset(
           &Layout->getAssembler().getSymbolData(Value.getSymA()->getSymbol()));
       }
       if (Value.getSymB()) {
-       Res -= Layout->getSymbolAddress(
+       Res -= Layout->getSymbolOffset(
           &Layout->getAssembler().getSymbolData(Value.getSymB()->getSymbol()));
       }
     }
@@ -283,8 +290,9 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
   return true;
 }
 
-static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
-                                const MCAssembler *Asm,
+static bool EvaluateSymbolicAdd(const MCAssembler *Asm,
+                                const MCAsmLayout *Layout,
+                                const SectionAddrMap *Addrs,
                                 bool InSet,
                                 const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
                                 const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
@@ -327,10 +335,19 @@ static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
       }
 
       if (Layout) {
-        Res = MCValue::get(+ Layout->getSymbolAddress(&AD)
-                           - Layout->getSymbolAddress(&BD)
-                           + LHS.getConstant()
-                           + RHS_Cst);
+        const MCSectionData &SecA = *AD.getFragment()->getParent();
+        const MCSectionData &SecB = *BD.getFragment()->getParent();
+        int64_t Val = + Layout->getSymbolOffset(&AD)
+                      - Layout->getSymbolOffset(&BD)
+                      + LHS.getConstant()
+                      + RHS_Cst;
+        if (&SecA != &SecB) {
+          if (!Addrs)
+            return false;
+          Val += Addrs->lookup(&SecA);
+          Val -= Addrs->lookup(&SecB);
+        }
+        Res = MCValue::get(Val);
         return true;
       }
     }
@@ -344,14 +361,15 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
                                    const MCAsmLayout *Layout) const {
   if (Layout)
     return EvaluateAsRelocatableImpl(Res, &Layout->getAssembler(), Layout,
-                                     false);
+                                     0, false);
   else
-    return EvaluateAsRelocatableImpl(Res, 0, 0, false);
+    return EvaluateAsRelocatableImpl(Res, 0, 0, 0, false);
 }
 
 bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
                                        const MCAssembler *Asm,
                                        const MCAsmLayout *Layout,
+                                       const SectionAddrMap *Addrs,
                                        bool InSet) const {
   ++stats::MCExprEvaluate;
 
@@ -371,6 +389,7 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
       bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm,
                                                                    Layout,
+                                                                   Addrs,
                                                                    true);
       // If we failed to simplify this to a constant, let the target
       // handle it.
@@ -387,7 +406,7 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     MCValue Value;
 
     if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout,
-                                                      InSet))
+                                                      Addrs, InSet))
       return false;
 
     switch (AUE->getOpcode()) {
@@ -421,9 +440,9 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     MCValue LHSValue, RHSValue;
 
     if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout,
-                                                  InSet) ||
+                                                  Addrs, InSet) ||
         !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout,
-                                                  InSet))
+                                                  Addrs, InSet))
       return false;
 
     // We only support a few operations on non-constant expressions, handle
@@ -434,13 +453,13 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
         return false;
       case MCBinaryExpr::Sub:
         // Negate RHS and add.
-        return EvaluateSymbolicAdd(Layout, Asm, InSet, LHSValue,
+        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
                                    RHSValue.getSymB(), RHSValue.getSymA(),
                                    -RHSValue.getConstant(),
                                    Res);
 
       case MCBinaryExpr::Add:
-        return EvaluateSymbolicAdd(Layout, Asm, InSet, LHSValue,
+        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
                                    RHSValue.getSymA(), RHSValue.getSymB(),
                                    RHSValue.getConstant(),
                                    Res);
index 1ee2d48..6f36001 100644 (file)
@@ -36,7 +36,7 @@ private:
 public:
   MCMachOStreamer(MCContext &Context, TargetAsmBackend &TAB,
                   raw_ostream &OS, MCCodeEmitter *Emitter)
-    : MCObjectStreamer(Context, TAB, OS, Emitter, true) {}
+    : MCObjectStreamer(Context, TAB, OS, Emitter) {}
 
   /// @name MCStreamer Interface
   /// @{
index 6348a2b..683f2c6 100644 (file)
 using namespace llvm;
 
 MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB,
-                                   raw_ostream &_OS, MCCodeEmitter *_Emitter,
-                                   bool _PadSectionToAlignment)
+                                   raw_ostream &_OS, MCCodeEmitter *_Emitter)
   : MCStreamer(Context), Assembler(new MCAssembler(Context, TAB,
                                                    *_Emitter,
-                                                   _PadSectionToAlignment,
                                                    _OS)),
     CurSectionData(0)
 {
index af23c91..5341844 100644 (file)
@@ -30,8 +30,7 @@ private:
 public:
   MCPureStreamer(MCContext &Context, TargetAsmBackend &TAB,
                  raw_ostream &OS, MCCodeEmitter *Emitter)
-    : MCObjectStreamer(Context, TAB, OS, Emitter,
-                       /*PadSectionToAlignment=*/true) {}
+    : MCObjectStreamer(Context, TAB, OS, Emitter) {}
 
   /// @name MCStreamer Interface
   /// @{
index 1236dc1..de96d64 100644 (file)
@@ -197,6 +197,34 @@ class MachObjectWriter : public MCObjectWriter {
 
   /// @}
 
+  SectionAddrMap SectionAddress;
+  uint64_t getSectionAddress(const MCSectionData* SD) const {
+    return SectionAddress.lookup(SD);
+  }
+  uint64_t getSymbolAddress(const MCSymbolData* SD,
+                            const MCAsmLayout &Layout) const {
+    return getSectionAddress(SD->getFragment()->getParent()) +
+      Layout.getSymbolOffset(SD);
+  }
+  uint64_t getFragmentAddress(const MCFragment *Fragment,
+                            const MCAsmLayout &Layout) const {
+    return getSectionAddress(Fragment->getParent()) +
+      Layout.getFragmentOffset(Fragment);
+  }
+
+  uint64_t getPaddingSize(const MCSectionData *SD,
+                          const MCAsmLayout &Layout) const {
+    uint64_t EndAddr = getSectionAddress(SD) + Layout.getSectionAddressSize(SD);
+    unsigned Next = SD->getLayoutOrder() + 1;
+    if (Next >= Layout.getSectionOrder().size())
+      return 0;
+
+    const MCSectionData &NextSD = *Layout.getSectionOrder()[Next];
+    if (NextSD.getSection().isVirtualSection())
+      return 0;
+    return OffsetToAlignment(EndAddr, NextSD.getAlignment());
+  }
+
   unsigned Is64Bit : 1;
 
   uint32_t CPUType;
@@ -283,7 +311,7 @@ public:
   void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
                     const MCSectionData &SD, uint64_t FileOffset,
                     uint64_t RelocationsStart, unsigned NumRelocations) {
-    uint64_t SectionSize = Layout.getSectionSize(&SD);
+    uint64_t SectionSize = Layout.getSectionAddressSize(&SD);
 
     // The offset is unused for virtual sections.
     if (SD.getSection().isVirtualSection()) {
@@ -301,10 +329,10 @@ public:
     WriteBytes(Section.getSectionName(), 16);
     WriteBytes(Section.getSegmentName(), 16);
     if (Is64Bit) {
-      Write64(Layout.getSectionAddress(&SD)); // address
+      Write64(getSectionAddress(&SD)); // address
       Write64(SectionSize); // size
     } else {
-      Write32(Layout.getSectionAddress(&SD)); // address
+      Write32(getSectionAddress(&SD)); // address
       Write32(SectionSize); // size
     }
     Write32(FileOffset);
@@ -413,7 +441,7 @@ public:
       if (Symbol.isAbsolute()) {
         Address = cast<MCConstantExpr>(Symbol.getVariableValue())->getValue();
       } else {
-        Address = Layout.getSymbolAddress(&Data);
+        Address = getSymbolAddress(&Data, Layout);
       }
     } else if (Data.isCommon()) {
       // Common symbols are encoded with the size in the address
@@ -473,7 +501,7 @@ public:
     uint32_t FixupOffset =
       Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
     uint32_t FixupAddress =
-      Layout.getFragmentAddress(Fragment) + Fixup.getOffset();
+      getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
     int64_t Value = 0;
     unsigned Index = 0;
     unsigned IsExtern = 0;
@@ -603,10 +631,21 @@ public:
         // The index is the section ordinal (1-based).
         Index = SD.getFragment()->getParent()->getOrdinal() + 1;
         IsExtern = 0;
-        Value += Layout.getSymbolAddress(&SD);
+        Value += getSymbolAddress(&SD, Layout);
 
         if (IsPCRel)
           Value -= FixupAddress + (1 << Log2Size);
+      } else if (Symbol->isVariable()) {
+        const MCExpr *Value = Symbol->getVariableValue();
+        int64_t Res;
+        bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, SectionAddress);
+        if (isAbs) {
+          FixedValue = Res;
+          return;
+        } else {
+          report_fatal_error("unsupported relocation of variable '" +
+                             Symbol->getName() + "'");
+        }
       } else {
         report_fatal_error("unsupported relocation of undefined symbol '" +
                            Symbol->getName() + "'");
@@ -708,7 +747,9 @@ public:
       report_fatal_error("symbol '" + A->getName() +
                         "' can not be undefined in a subtraction expression");
 
-    uint32_t Value = Layout.getSymbolAddress(A_SD);
+    uint32_t Value = getSymbolAddress(A_SD, Layout);
+    uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent());
+    FixedValue += SecAddr;
     uint32_t Value2 = 0;
 
     if (const MCSymbolRefExpr *B = Target.getSymB()) {
@@ -725,7 +766,8 @@ public:
       // for pedantic compatibility with 'as'.
       Type = A_SD->isExternal() ? macho::RIT_Difference :
         macho::RIT_LocalDifference;
-      Value2 = Layout.getSymbolAddress(B_SD);
+      Value2 = getSymbolAddress(B_SD, Layout);
+      FixedValue -= getSectionAddress(B_SD->getFragment()->getParent());
     }
 
     // Relocations are written out in reverse order, so the PAIR comes first.
@@ -774,10 +816,10 @@ public:
     if (Target.getSymB()) {
       // If this is a subtraction then we're pcrel.
       uint32_t FixupAddress =
-      Layout.getFragmentAddress(Fragment) + Fixup.getOffset();
+        getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
       MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol());
       IsPCRel = 1;
-      FixedValue = (FixupAddress - Layout.getSymbolAddress(SD_B) +
+      FixedValue = (FixupAddress - getSymbolAddress(SD_B, Layout) +
                     Target.getConstant());
       FixedValue += 1ULL << Log2Size;
     } else {
@@ -855,10 +897,13 @@ public:
         // compensate for the addend of the symbol address, if it was
         // undefined. This occurs with weak definitions, for example.
         if (!SD->Symbol->isUndefined())
-          FixedValue -= Layout.getSymbolAddress(SD);
+          FixedValue -= getSymbolAddress(SD, Layout);
       } else {
         // The index is the section ordinal (1-based).
         Index = SD->getFragment()->getParent()->getOrdinal() + 1;
+        FixedValue += getSectionAddress(SD->getFragment()->getParent());
+        if (IsPCRel)
+          FixedValue -= getSectionAddress(Fragment->getParent());
       }
 
       Type = macho::RIT_Vanilla;
@@ -1039,7 +1084,25 @@ public:
       StringTable += '\x00';
   }
 
-  void ExecutePostLayoutBinding(MCAssembler &Asm) {
+  void computeSectionAddresses(const MCAssembler &Asm,
+                               const MCAsmLayout &Layout) {
+    uint64_t StartAddress = 0;
+    const SmallVectorImpl<MCSectionData*> &Order = Layout.getSectionOrder();
+    for (int i = 0, n = Order.size(); i != n ; ++i) {
+      const MCSectionData *SD = Order[i];
+      StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment());
+      SectionAddress[SD] = StartAddress;
+      StartAddress += Layout.getSectionAddressSize(SD);
+      // Explicitly pad the section to match the alignment requirements of the
+      // following one. This is for 'gas' compatibility, it shouldn't
+      /// strictly be necessary.
+      StartAddress += getPaddingSize(SD, Layout);
+    }
+  }
+
+  void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) {
+    computeSectionAddresses(Asm, Layout);
+
     // Create symbol data for any indirect symbols.
     BindIndirectSymbols(Asm);
 
@@ -1113,9 +1176,10 @@ public:
     for (MCAssembler::const_iterator it = Asm.begin(),
            ie = Asm.end(); it != ie; ++it) {
       const MCSectionData &SD = *it;
-      uint64_t Address = Layout.getSectionAddress(&SD);
-      uint64_t Size = Layout.getSectionSize(&SD);
+      uint64_t Address = getSectionAddress(&SD);
+      uint64_t Size = Layout.getSectionAddressSize(&SD);
       uint64_t FileSize = Layout.getSectionFileSize(&SD);
+      FileSize += getPaddingSize(&SD, Layout);
 
       VMSize = std::max(VMSize, Address + Size);
 
@@ -1144,7 +1208,7 @@ public:
            ie = Asm.end(); it != ie; ++it) {
       std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
       unsigned NumRelocs = Relocs.size();
-      uint64_t SectionStart = SectionDataStart + Layout.getSectionAddress(it);
+      uint64_t SectionStart = SectionDataStart + getSectionAddress(it);
       WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs);
       RelocTableEnd += NumRelocs * macho::RelocationInfoSize;
     }
@@ -1185,9 +1249,14 @@ public:
 
     // Write the actual section data.
     for (MCAssembler::const_iterator it = Asm.begin(),
-           ie = Asm.end(); it != ie; ++it)
+           ie = Asm.end(); it != ie; ++it) {
       Asm.WriteSectionData(it, Layout, this);
 
+      uint64_t Pad = getPaddingSize(it, Layout);
+      for (unsigned int i = 0; i < Pad; ++i)
+        Write8(0);
+    }
+
     // Write the extra padding.
     WriteZeros(SectionDataPadding);
 
index 1bfd3a4..66fd920 100644 (file)
@@ -170,7 +170,7 @@ public:
 
   // MCObjectWriter interface implementation.
 
-  void ExecutePostLayoutBinding(MCAssembler &Asm);
+  void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout);
 
   void RecordRelocation(const MCAssembler &Asm,
                         const MCAsmLayout &Layout,
@@ -616,7 +616,8 @@ void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
 ////////////////////////////////////////////////////////////////////////////////
 // MCObjectWriter interface implementations
 
-void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
+void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
+                                                   const MCAsmLayout &Layout) {
   // "Define" each section & symbol. This creates section & symbol
   // entries in the staging area.
 
@@ -753,7 +754,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
 
   for (sections::iterator i = Sections.begin(),
                           e = Sections.end(); i != e; i++) {
-    if (Layout.getSectionSize((*i)->MCData) > 0) {
+    if (Layout.getSectionAddressSize((*i)->MCData) > 0) {
       MakeSectionReal(**i, ++Header.NumberOfSections);
     } else {
       (*i)->Number = -1;
index 3654add..46968e6 100644 (file)
@@ -124,7 +124,7 @@ WinCOFFStreamer::WinCOFFStreamer(MCContext &Context,
                                  TargetAsmBackend &TAB,
                                  MCCodeEmitter &CE,
                                  raw_ostream &OS)
-    : MCObjectStreamer(Context, TAB, OS, &CE, false)
+    : MCObjectStreamer(Context, TAB, OS, &CE)
     , CurSymbol(NULL) {
 }