Write => in a more normal form.
[oota-llvm.git] / lib / MC / MCAssembler.cpp
index 319f04cfe707981409fb71909271977118dfa561..243975c2bc6cadd30c79646f8cba0b0203b1440b 100644 (file)
@@ -74,10 +74,9 @@ void MCAsmLayout::Invalidate(MCFragment *F) {
   if (!isFragmentUpToDate(F))
     return;
 
-  // Otherwise, reset the last valid fragment to the predecessor of the
-  // invalidated fragment.
+  // Otherwise, reset the last valid fragment to this fragment.
   const MCSectionData &SD = *F->getParent();
-  LastValidFragment[&SD] = F->getPrevNode();
+  LastValidFragment[&SD] = F;
 }
 
 void MCAsmLayout::EnsureValid(const MCFragment *F) const {
@@ -96,12 +95,6 @@ void MCAsmLayout::EnsureValid(const MCFragment *F) const {
   }
 }
 
-uint64_t MCAsmLayout::getFragmentEffectiveSize(const MCFragment *F) const {
-  EnsureValid(F);
-  assert(F->EffectiveSize != ~UINT64_C(0) && "Address not set!");
-  return F->EffectiveSize;
-}
-
 uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const {
   EnsureValid(F);
   assert(F->Offset != ~UINT64_C(0) && "Address not set!");
@@ -116,7 +109,7 @@ uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const {
 uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {
   // The size is the last fragment's end offset.
   const MCFragment &F = SD->getFragmentList().back();
-  return getFragmentOffset(&F) + getFragmentEffectiveSize(&F);
+  return getFragmentOffset(&F) + getAssembler().ComputeFragmentSize(F);
 }
 
 uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const {
@@ -137,8 +130,7 @@ MCFragment::~MCFragment() {
 }
 
 MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent)
-  : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0)),
-    EffectiveSize(~UINT64_C(0))
+  : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0))
 {
   if (Parent)
     Parent->getFragmentList().push_back(this);
@@ -232,15 +224,18 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
 
   Value = Target.getConstant();
 
-  bool IsPCRel = Emitter.getFixupKindInfo(
+  bool IsPCRel = Backend.getFixupKindInfo(
     Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
   bool IsResolved = true;
+  bool IsThumb = false;
   if (const MCSymbolRefExpr *A = Target.getSymA()) {
     const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
     if (Sym.isDefined())
       Value += Layout.getSymbolOffset(&getSymbolData(Sym));
     else
       IsResolved = false;
+    if (isThumbFunc(&Sym))
+      IsThumb = true;
   }
   if (const MCSymbolRefExpr *B = Target.getSymB()) {
     const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
@@ -253,21 +248,31 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
   if (IsResolved)
     IsResolved = Writer.IsFixupFullyResolved(*this, Target, IsPCRel, DF);
 
+  bool ShouldAlignPC = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
+                         MCFixupKindInfo::FKF_IsAlignedDownTo32Bits;
+  assert((ShouldAlignPC ? IsPCRel : true) &&
+    "FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!");
+
   if (IsPCRel) {
-    bool ShouldAlignPC = Emitter.getFixupKindInfo(
-                        Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsAligned;
-    // PC should be aligned to a 4-byte value.
-    if (ShouldAlignPC)
-      Value -= Layout.getFragmentOffset(DF) + (Fixup.getOffset() & ~0x3);
-    else
-      Value -= Layout.getFragmentOffset(DF) + Fixup.getOffset();
+    uint32_t Offset = Fixup.getOffset();
+    
+    // A number of ARM fixups in Thumb mode require that the effective PC
+    // address be determined as the 32-bit aligned version of the actual offset.
+    if (ShouldAlignPC) Offset &= ~0x3;
+    Value -= Layout.getFragmentOffset(DF) + Offset;
   }
 
+  // ARM fixups based from a thumb function address need to have the low
+  // bit set. The actual value is always at least 16-bit aligned, so the
+  // low bit is normally clear and available for use as an ISA flag for
+  // interworking.
+  if (IsThumb)
+    Value |= 1;
+
   return IsResolved;
 }
 
-uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
-                                          uint64_t FragmentOffset) const {
+uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F) const {
   switch (F.getKind()) {
   case MCFragment::FT_Data:
     return cast<MCDataFragment>(F).getContents().size();
@@ -279,17 +284,8 @@ uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
   case MCFragment::FT_LEB:
     return cast<MCLEBFragment>(F).getContents().size();
 
-  case MCFragment::FT_Align: {
-    const MCAlignFragment &AF = cast<MCAlignFragment>(F);
-
-    uint64_t Size = OffsetToAlignment(FragmentOffset, AF.getAlignment());
-
-    // Honor MaxBytesToEmit.
-    if (Size > AF.getMaxBytesToEmit())
-      return 0;
-
-    return Size;
-  }
+  case MCFragment::FT_Align:
+    return cast<MCAlignFragment>(F).getSize();
 
   case MCFragment::FT_Org:
     return cast<MCOrgFragment>(F).getSize();
@@ -317,10 +313,9 @@ void MCAsmLayout::LayoutFragment(MCFragment *F) {
   // Compute fragment offset and size.
   uint64_t Offset = 0;
   if (Prev)
-    Offset += Prev->Offset + Prev->EffectiveSize;
+    Offset += Prev->Offset + getAssembler().ComputeFragmentSize(*Prev);
 
   F->Offset = Offset;
-  F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, F->Offset);
   LastValidFragment[F->getParent()] = F;
 }
 
@@ -333,7 +328,7 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
   ++stats::EmittedFragments;
 
   // FIXME: Embed in fragments instead?
-  uint64_t FragmentSize = Layout.getFragmentEffectiveSize(&F);
+  uint64_t FragmentSize = Asm.ComputeFragmentSize(F);
   switch (F.getKind()) {
   case MCFragment::FT_Align: {
     MCAlignFragment &AF = cast<MCAlignFragment>(F);
@@ -720,6 +715,18 @@ bool MCAssembler::RelaxDwarfLineAddr(const MCObjectWriter &Writer,
   return OldSize != Data.size();
 }
 
+bool MCAssembler::RelaxAlignment(const MCObjectWriter &Writer,
+                                MCAsmLayout &Layout,
+                                MCAlignFragment &AF) {
+  unsigned Offset = Layout.getFragmentOffset(&AF);
+  unsigned Size = OffsetToAlignment(Offset, AF.getAlignment());
+  if (Size > AF.getMaxBytesToEmit())
+    Size = 0;
+  unsigned OldSize = AF.getSize();
+  AF.setSize(Size);
+  return OldSize != Size;
+}
+
 bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
                              MCAsmLayout &Layout) {
   ++stats::RelaxationSteps;
@@ -728,6 +735,7 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
   bool WasRelaxed = false;
   for (iterator it = begin(), ie = end(); it != ie; ++it) {
     MCSectionData &SD = *it;
+    MCFragment *FirstInvalidFragment = NULL;
 
     for (MCSectionData::iterator it2 = SD.begin(),
            ie2 = SD.end(); it2 != ie2; ++it2) {
@@ -736,6 +744,10 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
       switch(it2->getKind()) {
       default:
         break;
+      case MCFragment::FT_Align:
+       relaxedFrag = RelaxAlignment(Writer, Layout,
+                                    *cast<MCAlignFragment>(it2));
+       break;
       case MCFragment::FT_Inst:
         relaxedFrag = RelaxInstruction(Writer, Layout,
                                        *cast<MCInstFragment>(it2));
@@ -752,10 +764,12 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
         break;
       }
       // Update the layout, and remember that we relaxed.
-      if (relaxedFrag)
-       Layout.Invalidate(it2);
+      if (relaxedFrag && !FirstInvalidFragment)
+        FirstInvalidFragment = it2;
       WasRelaxed |= relaxedFrag;
     }
+    if (FirstInvalidFragment)
+      Layout.Invalidate(FirstInvalidFragment);
   }
 
   return WasRelaxed;
@@ -796,7 +810,7 @@ void MCFragment::dump() {
   }
 
   OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
-     << " Offset:" << Offset << " EffectiveSize:" << EffectiveSize << ">";
+     << " Offset:" << Offset << ">";
 
   switch (getKind()) {
   case MCFragment::FT_Align: {