[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