[PATCH v2 0/14] [x86] Fix 16-bit addressing modes (PR18220) and implement .code16 (PR8684)

David Woodhouse dwmw2 at infradead.org
Fri Dec 20 14:41:23 PST 2013


On Fri, 2013-12-20 at 21:16 +0000, David Woodhouse wrote:
> 
> I'm guessing the relocation fixups are happening after the .code16
> switch has been processed? How does this work?

Badly, it seems. Looks like the same problem would affect .code32
vs. .code64 where instructions get re-encoded after a mode switch has
been processed.

Now I get to show my C++ ignorance a little more. I was trying to keep
the mode changes in the fragment list so that they could be "played
back" as we were going through and relaxing instructions. What did I do
wrong here?:

/home/dwmw2/git/llvm/Debug+Asserts/lib/libLLVMMC.a(MCELFStreamer.o): In function `MCModeSwitchFragment':
/home/dwmw2/git/llvm/include/llvm/MC/MCAssembler.h:802: undefined reference to `vtable for llvm::MCModeSwitchFragment'

Half-finished patch on top of my git tree (it only records the mode
switches; doesn't actually do anything with the information):

diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 8735a55..e90ce69 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/ilist_node.h"
 #include "llvm/MC/MCFixup.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCDirectives.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/DataTypes.h"
 #include <algorithm>
@@ -54,7 +55,8 @@ public:
     FT_Org,
     FT_Dwarf,
     FT_DwarfFrame,
-    FT_LEB
+    FT_LEB,
+    FT_ModeSwitch
   };
 
 private:
@@ -788,6 +790,30 @@ public:
   void dump();
 };
 
+class MCModeSwitchFragment : public MCFragment {
+  virtual void anchor();
+
+  /// Offset - The offset this fragment should start at.
+  const MCAssemblerFlag Mode;
+
+public:
+  MCModeSwitchFragment(const MCAssemblerFlag _Mode, MCSectionData *SD = 0)
+    : MCFragment(FT_ModeSwitch, SD),
+      Mode(_Mode) {}
+
+  /// @name Accessors
+  /// @{
+
+  MCAssemblerFlag getMode() const { return Mode; }
+
+  /// @}
+
+  static bool classof(const MCFragment *F) {
+    return F->getKind() == MCFragment::FT_ModeSwitch;
+  }
+};
+
+
 // FIXME: This really doesn't belong here. See comments below.
 struct IndirectSymbolData {
   MCSymbol *Symbol;
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 68111f1..c069698 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -425,6 +425,8 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
 uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
                                           const MCFragment &F) const {
   switch (F.getKind()) {
+  case MCFragment::FT_ModeSwitch:
+    return 0;
   case MCFragment::FT_Data:
   case MCFragment::FT_Relaxable:
   case MCFragment::FT_CompactEncodedInst:
@@ -676,6 +678,8 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
     OW->WriteBytes(CF.getContents().str());
     break;
   }
+  case MCFragment::FT_ModeSwitch:
+    break;
   }
 
   assert(OW->getStream().tell() - Start == FragmentSize &&
@@ -936,7 +940,7 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout,
   OSE.flush();
   return OldSize != Data.size();
 }
-
+#include <stdio.h>
 bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD) {
   // Holds the first fragment which needed relaxing during this layout. It will
   // remain NULL if none were relaxed.
@@ -952,6 +956,7 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD) {
     default:
       break;
     case MCFragment::FT_Relaxable:
+	    ::printf("Will relax an insn now\n");
       assert(!getRelaxAll() &&
              "Did not expect a MCRelaxableFragment in RelaxAll mode");
       RelaxedFrag = relaxInstruction(Layout, *cast<MCRelaxableFragment>(I));
@@ -968,6 +973,8 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD) {
     case MCFragment::FT_LEB:
       RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I));
       break;
+    case MCFragment::FT_ModeSwitch:
+	    ::printf("Will mode switch now\n");
     }
     if (RelaxedFrag && !FirstRelaxedFragment)
       FirstRelaxedFragment = I;
@@ -1018,6 +1025,7 @@ void MCFragment::dump() {
 
   OS << "<";
   switch (getKind()) {
+  case MCFragment::FT_ModeSwitch: OS << "MCModeSwitchFragment"; break;
   case MCFragment::FT_Align: OS << "MCAlignFragment"; break;
   case MCFragment::FT_Data:  OS << "MCDataFragment"; break;
   case MCFragment::FT_CompactEncodedInst:
@@ -1120,6 +1128,24 @@ void MCFragment::dump() {
     OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
     break;
   }
+  case MCFragment::FT_ModeSwitch: {
+    const MCModeSwitchFragment *MF = cast<MCModeSwitchFragment>(this);
+    OS << "\n       ";
+    OS << " Mode: ";
+    switch(MF->getMode()) {
+    case MCAF_Code16:
+      OS << "code16";
+      break;
+    case MCAF_Code32:
+      OS << "code32";
+      break;
+    case MCAF_Code64:
+      OS << "code64";
+      break;
+    default:
+      break;
+    }
+  }
   }
   OS << ">";
 }
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index b601785..c2c90ea 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -102,9 +102,11 @@ void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
   // Do any generic stuff we need to do.
   switch (Flag) {
   case MCAF_SyntaxUnified: return; // no-op here.
-  case MCAF_Code16: return; // Change parsing mode; no-op here.
-  case MCAF_Code32: return; // Change parsing mode; no-op here.
-  case MCAF_Code64: return; // Change parsing mode; no-op here.
+  case MCAF_Code16:
+  case MCAF_Code32:
+  case MCAF_Code64:
+    insert(new MCModeSwitchFragment(Flag));
+    return;
   case MCAF_SubsectionsViaSymbols:
     getAssembler().setSubsectionsViaSymbols(true);
     return;


-- 
dwmw2





More information about the llvm-commits mailing list