Initialize HasPOPCNT.
[oota-llvm.git] / lib / MC / MCAssembler.cpp
index c80dc3c2483219908c4ca6e76a3a0c775ae8a775..1e701ecf2b4b50186610889aed52891a6d91b7ab 100644 (file)
@@ -54,10 +54,10 @@ MCAsmLayout::MCAsmLayout(MCAssembler &Asm)
  {
   // Compute the section layout order. Virtual sections must go last.
   for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
-    if (!Asm.getBackend().isVirtualSection(it->getSection()))
+    if (!it->getSection().isVirtualSection())
       SectionOrder.push_back(&*it);
   for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
-    if (Asm.getBackend().isVirtualSection(it->getSection()))
+    if (it->getSection().isVirtualSection())
       SectionOrder.push_back(&*it);
 }
 
@@ -78,7 +78,7 @@ bool MCAsmLayout::isFragmentUpToDate(const MCFragment *F) const {
           F->getLayoutOrder() <= LastValidFragment->getLayoutOrder());
 }
 
-void MCAsmLayout::UpdateForSlide(MCFragment *F, int SlideAmount) {
+void MCAsmLayout::Invalidate(MCFragment *F) {
   // If this fragment wasn't already up-to-date, we don't need to do anything.
   if (!isFragmentUpToDate(F))
     return;
@@ -113,12 +113,28 @@ void MCAsmLayout::EnsureValid(const MCFragment *F) const {
   }
 }
 
-void MCAsmLayout::FragmentReplaced(MCFragment *Src, MCFragment *Dst) {
-  if (LastValidFragment == Src)
-    LastValidFragment = Dst;
+void MCAsmLayout::ReplaceFragment(MCFragment *Src, MCFragment *Dst) {
+  MCSectionData *SD = Src->getParent();
+
+  // Insert Dst immediately before Src
+  SD->getFragmentList().insert(Src, Dst);
+
+  // Set the data fragment's layout data.
+  Dst->setParent(Src->getParent());
+  Dst->setAtom(Src->getAtom());
 
   Dst->Offset = Src->Offset;
   Dst->EffectiveSize = Src->EffectiveSize;
+
+  // Remove Src, but don't delete it yet.
+  SD->getFragmentList().remove(Src);
+}
+
+void MCAsmLayout::CoalesceFragments(MCFragment *Src, MCFragment *Dst) {
+  assert(Src->getPrevNode() == Dst);
+  Dst->EffectiveSize += Src->EffectiveSize;
+  // Remove Src, but don't delete it yet.
+  Src->getParent()->getFragmentList().remove(Src);
 }
 
 uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const {
@@ -157,7 +173,7 @@ uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {
 
 uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const {
   // Virtual sections have no file size.
-  if (getAssembler().getBackend().isVirtualSection(SD->getSection()))
+  if (SD->getSection().isVirtualSection())
     return 0;
 
   // Otherwise, the file size is the same as the address space size.
@@ -308,8 +324,7 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
   return IsResolved;
 }
 
-uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout,
-                                          const MCFragment &F,
+uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
                                           uint64_t SectionAddress,
                                           uint64_t FragmentOffset) const {
   switch (F.getKind()) {
@@ -321,7 +336,7 @@ uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout,
     return cast<MCInstFragment>(F).getInstSize();
 
   case MCFragment::FT_LEB:
-    return cast<MCLEBFragment>(F).getSize();
+    return cast<MCLEBFragment>(F).getContents().size();
 
   case MCFragment::FT_Align: {
     const MCAlignFragment &AF = cast<MCAlignFragment>(F);
@@ -343,7 +358,7 @@ uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout,
     return cast<MCOrgFragment>(F).getSize();
 
   case MCFragment::FT_Dwarf:
-    return cast<MCDwarfLineAddrFragment>(F).getSize();
+    return cast<MCDwarfLineAddrFragment>(F).getContents().size();
   }
 
   assert(0 && "invalid fragment kind");
@@ -382,7 +397,7 @@ void MCAsmLayout::LayoutFragment(MCFragment *F) {
 
   // Compute fragment offset and size.
   F->Offset = Address - StartAddress;
-  F->EffectiveSize = getAssembler().ComputeFragmentSize(*this, *F, StartAddress,
+  F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, StartAddress,
                                                         F->Offset);
   LastValidFragment = F;
 
@@ -495,18 +510,7 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
 
   case MCFragment::FT_LEB: {
     MCLEBFragment &LF = cast<MCLEBFragment>(F);
-
-    // FIXME: It is probably better if we don't call EvaluateAsAbsolute in
-    // here.
-    int64_t Value;
-    LF.getValue().EvaluateAsAbsolute(Value, &Layout);
-    SmallString<32> Tmp;
-    raw_svector_ostream OSE(Tmp);
-    if (LF.isSigned())
-      MCObjectWriter::EncodeSLEB128(Value, OSE);
-    else
-      MCObjectWriter::EncodeULEB128(Value, OSE);
-    OW->WriteBytes(OSE.str());
+    OW->WriteBytes(LF.getContents().str());
     break;
   }
 
@@ -521,15 +525,7 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
 
   case MCFragment::FT_Dwarf: {
     const MCDwarfLineAddrFragment &OF = cast<MCDwarfLineAddrFragment>(F);
-
-    // The AddrDelta is really unsigned and it can only increase.
-    int64_t AddrDelta;
-    OF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, &Layout);
-
-    int64_t LineDelta;
-    LineDelta = OF.getLineDelta();
-
-    MCDwarfLineAddr::Write(OW, LineDelta, (uint64_t)AddrDelta);
+    OW->WriteBytes(OF.getContents().str());
     break;
   }
   }
@@ -541,7 +537,7 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD,
                                    const MCAsmLayout &Layout,
                                    MCObjectWriter *OW) const {
   // Ignore virtual sections.
-  if (getBackend().isVirtualSection(SD->getSection())) {
+  if (SD->getSection().isVirtualSection()) {
     assert(Layout.getSectionFileSize(SD) == 0 && "Invalid size for section!");
 
     // Check that contents are only things legal inside a virtual section.
@@ -589,26 +585,6 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD,
   assert(OW->getStream().tell() - Start == Layout.getSectionFileSize(SD));
 }
 
-void MCAssembler::AddSectionToTheEnd(const MCObjectWriter &Writer,
-                                     MCSectionData &SD, MCAsmLayout &Layout) {
-  // Create dummy fragments and assign section ordinals.
-  unsigned SectionIndex = size();
-  SD.setOrdinal(SectionIndex);
-
-  // Assign layout order indices to sections and fragments.
-  const MCFragment &Last = *Layout.getSectionOrder().back()->rbegin();
-  unsigned FragmentIndex = Last.getLayoutOrder() + 1;
-
-  SD.setLayoutOrder(Layout.getSectionOrder().size());
-  for (MCSectionData::iterator it2 = SD.begin(),
-         ie2 = SD.end(); it2 != ie2; ++it2) {
-    it2->setLayoutOrder(FragmentIndex++);
-  }
-  Layout.getSectionOrder().push_back(&SD);
-
-  Layout.LayoutSection(&SD);
-}
-
 void MCAssembler::Finish(MCObjectWriter *Writer) {
   DEBUG_WITH_TYPE("mc-dump", {
       llvm::errs() << "assembler backend - pre-layout\n--\n";
@@ -630,7 +606,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
         continue;
 
       // Ignore virtual sections, they don't cause file size modifications.
-      if (getBackend().isVirtualSection(SD->getSection()))
+      if (SD->getSection().isVirtualSection())
         continue;
 
       // Otherwise, create a new align fragment at the end of the previous
@@ -789,7 +765,6 @@ bool MCAssembler::RelaxInstruction(const MCObjectWriter &Writer,
   VecOS.flush();
 
   // Update the instruction fragment.
-  int SlideAmount = Code.size() - IF.getInstSize();
   IF.setInst(Relaxed);
   IF.getCode() = Code;
   IF.getFixups().clear();
@@ -797,8 +772,6 @@ bool MCAssembler::RelaxInstruction(const MCObjectWriter &Writer,
   for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
     IF.getFixups().push_back(Fixups[i]);
 
-  // Update the layout, and remember that we relaxed.
-  Layout.UpdateForSlide(&IF, SlideAmount);
   return true;
 }
 
@@ -824,29 +797,34 @@ bool MCAssembler::RelaxOrg(const MCObjectWriter &Writer,
 bool MCAssembler::RelaxLEB(const MCObjectWriter &Writer,
                            MCAsmLayout &Layout,
                            MCLEBFragment &LF) {
-  int64_t Value;
+  int64_t Value = 0;
+  uint64_t OldSize = LF.getContents().size();
   LF.getValue().EvaluateAsAbsolute(Value, &Layout);
-  SmallString<32> Tmp;
-  raw_svector_ostream OSE(Tmp);
+  SmallString<8> &Data = LF.getContents();
+  Data.clear();
+  raw_svector_ostream OSE(Data);
   if (LF.isSigned())
     MCObjectWriter::EncodeSLEB128(Value, OSE);
   else
     MCObjectWriter::EncodeULEB128(Value, OSE);
-  uint64_t OldSize = LF.getSize();
-  LF.setSize(OSE.GetNumBytesInBuffer());
-  return OldSize != LF.getSize();
+  OSE.flush();
+  return OldSize != LF.getContents().size();
 }
 
 bool MCAssembler::RelaxDwarfLineAddr(const MCObjectWriter &Writer,
                                     MCAsmLayout &Layout,
                                     MCDwarfLineAddrFragment &DF) {
-  int64_t AddrDelta;
+  int64_t AddrDelta = 0;
+  uint64_t OldSize = DF.getContents().size();
   DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, &Layout);
   int64_t LineDelta;
   LineDelta = DF.getLineDelta();
-  uint64_t OldSize = DF.getSize();
-  DF.setSize(MCDwarfLineAddr::ComputeSize(LineDelta, AddrDelta));
-  return OldSize != DF.getSize();  
+  SmallString<8> &Data = DF.getContents();
+  Data.clear();
+  raw_svector_ostream OSE(Data);
+  MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OSE);
+  OSE.flush();
+  return OldSize != Data.size();
 }
 
 bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
@@ -864,30 +842,51 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
     for (MCSectionData::iterator it2 = SD.begin(),
            ie2 = SD.end(); it2 != ie2; ++it2) {
       // Check if this is an fragment that needs relaxation.
+      bool relaxedFrag = false;
       switch(it2->getKind()) {
       default:
         break;
       case MCFragment::FT_Inst:
-        WasRelaxed |= RelaxInstruction(Writer, Layout,
+        relaxedFrag = RelaxInstruction(Writer, Layout,
                                        *cast<MCInstFragment>(it2));
         break;
       case MCFragment::FT_Org:
-        WasRelaxed |= RelaxOrg(Writer, Layout, *cast<MCOrgFragment>(it2));
+        relaxedFrag = RelaxOrg(Writer, Layout, *cast<MCOrgFragment>(it2));
         break;
       case MCFragment::FT_Dwarf:
-        WasRelaxed |= RelaxDwarfLineAddr(Writer, Layout,
+        relaxedFrag = RelaxDwarfLineAddr(Writer, Layout,
                                         *cast<MCDwarfLineAddrFragment>(it2));
        break;
       case MCFragment::FT_LEB:
-        WasRelaxed |= RelaxLEB(Writer, Layout, *cast<MCLEBFragment>(it2));
+        relaxedFrag = RelaxLEB(Writer, Layout, *cast<MCLEBFragment>(it2));
         break;
       }
+      // Update the layout, and remember that we relaxed.
+      if (relaxedFrag)
+       Layout.Invalidate(it2);
+      WasRelaxed |= relaxedFrag;
     }
   }
 
   return WasRelaxed;
 }
 
+static void LowerInstFragment(MCInstFragment *IF,
+                              MCDataFragment *DF) {
+
+  uint64_t DataOffset = DF->getContents().size();
+
+  // Copy in the data
+  DF->getContents().append(IF->getCode().begin(), IF->getCode().end());
+
+  // Adjust the fixup offsets and add them to the data fragment.
+  for (unsigned i = 0, e = IF->getFixups().size(); i != e; ++i) {
+    MCFixup &F = IF->getFixups()[i];
+    F.setOffset(DataOffset + F.getOffset());
+    DF->getFixups().push_back(F);
+  }
+}
+
 void MCAssembler::FinishLayout(MCAsmLayout &Layout) {
   // Lower out any instruction fragments, to simplify the fixup application and
   // output.
@@ -896,35 +895,46 @@ void MCAssembler::FinishLayout(MCAsmLayout &Layout) {
   // cheap (we will mostly end up eliminating fragments and appending on to data
   // fragments), so the extra complexity downstream isn't worth it. Evaluate
   // this assumption.
-  for (iterator it = begin(), ie = end(); it != ie; ++it) {
-    MCSectionData &SD = *it;
+
+  // The layout is done. Mark every fragment as valid.
+  Layout.getFragmentOffset(&*Layout.getSectionOrder().back()->rbegin());
+
+  unsigned FragmentIndex = 0;
+  for (unsigned i = 0, e = Layout.getSectionOrder().size(); i != e; ++i) {
+    MCSectionData &SD = *Layout.getSectionOrder()[i];
+    MCDataFragment *CurDF = NULL;
 
     for (MCSectionData::iterator it2 = SD.begin(),
            ie2 = SD.end(); it2 != ie2; ++it2) {
-      MCInstFragment *IF = dyn_cast<MCInstFragment>(it2);
-      if (!IF)
-        continue;
+      switch (it2->getKind()) {
+      default:
+        CurDF = NULL;
+        break;
+      case MCFragment::FT_Data:
+        CurDF = cast<MCDataFragment>(it2);
+        break;
+      case MCFragment::FT_Inst: {
+        MCInstFragment *IF = cast<MCInstFragment>(it2);
+        // Use the existing data fragment if possible.
+        if (CurDF && CurDF->getAtom() == IF->getAtom()) {
+          Layout.CoalesceFragments(IF, CurDF);
+        } else {
+          // Otherwise, create a new data fragment.
+          CurDF = new MCDataFragment();
+          Layout.ReplaceFragment(IF, CurDF);
+        }
 
-      // Create a new data fragment for the instruction.
-      //
-      // FIXME-PERF: Reuse previous data fragment if possible.
-      MCDataFragment *DF = new MCDataFragment();
-      SD.getFragmentList().insert(it2, DF);
-
-      // Update the data fragments layout data.
-      DF->setParent(IF->getParent());
-      DF->setAtom(IF->getAtom());
-      DF->setLayoutOrder(IF->getLayoutOrder());
-      Layout.FragmentReplaced(IF, DF);
-
-      // Copy in the data and the fixups.
-      DF->getContents().append(IF->getCode().begin(), IF->getCode().end());
-      for (unsigned i = 0, e = IF->getFixups().size(); i != e; ++i)
-        DF->getFixups().push_back(IF->getFixups()[i]);
-
-      // Delete the instruction fragment and update the iterator.
-      SD.getFragmentList().erase(IF);
-      it2 = DF;
+        // Lower the Instruction Fragment
+        LowerInstFragment(IF, CurDF);
+
+        // Delete the instruction fragment and update the iterator.
+        delete IF;
+        it2 = CurDF;
+        break;
+      }
+      }
+      // Since we may have merged fragments, fix the layout order.
+      it2->setLayoutOrder(FragmentIndex++);
     }
   }
 }