Index: src/IceFixups.cpp |
diff --git a/src/IceFixups.cpp b/src/IceFixups.cpp |
index b323bc611561a9d61e66286fb2e7636ea88c5aaf..3e982302ffe23bb15ed81f2a5e6294f530056bba 100644 |
--- a/src/IceFixups.cpp |
+++ b/src/IceFixups.cpp |
@@ -40,7 +40,9 @@ IceString AssemblerFixup::symbol(const GlobalContext *Ctx, |
Str << CR->getName(); |
else |
Str << Ctx->mangleName(CR->getName()); |
- if (Asm && !Asm->fixupIsPCRel(kind()) && Ctx->getFlags().getUseNonsfi()) { |
+ if (Asm && !Asm->fixupIsPCRel(kind()) && Ctx->getFlags().getUseNonsfi() && |
+ CR->getName() != GlobalOffsetTable) { |
+ // TODO(jpp): remove the special GOT test. |
Str << "@GOTOFF"; |
} |
} else { |
@@ -58,23 +60,49 @@ size_t AssemblerFixup::emit(GlobalContext *Ctx, const Assembler &Asm) const { |
return FixupSize; |
Ostream &Str = Ctx->getStrEmit(); |
Str << "\t.long "; |
- if (isNullSymbol()) |
+ IceString Symbol; |
+ if (isNullSymbol()) { |
Str << "__Sz_AbsoluteZero"; |
- else |
- Str << symbol(Ctx, &Asm); |
- RelocOffsetT Offset = Asm.load<RelocOffsetT>(position()); |
- if (Offset) |
- Str << " + " << Offset; |
- // For PCRel fixups, we write the pc-offset from a symbol into the Buffer |
- // (e.g., -4), but we don't represent that in the fixup's offset. Otherwise |
- // the fixup holds the true offset, and so does the Buffer. Just load the |
- // offset from the buffer. |
- if (Asm.fixupIsPCRel(kind())) |
+ } else { |
+ Symbol = symbol(Ctx, &Asm); |
+ Str << Symbol; |
+ } |
+ // The old behavior was x86 specific: emit expected a relocatable addend to |
+ // "live" in the 4 bytes starting at position(). This is not portable (e.g., |
+ // ARM32 relocations are hardly ever 32-bits.) |
+ // |
+ // The new behavior: offset() contains the offset that used to be stored in |
+ // the instruction stream, so we use it instead of the value at |
+ // Asm.Buffer[position()]. |
+ // |
+ // We leave an assert behind to detect any uses that still write anything but |
+ // a zero in the instruction stream. |
+ // |
+ // TODO(jpp): this behavior is also not portable. Ideally, X86 should define |
+ // its own sets of relocatables, and define emit as it pleases. |
+ assert(Asm.load<RelocOffsetT>(position()) == 0); |
+ |
+ RelocOffsetT Offset = offset(); |
+ if (Offset != 0) { |
+ if (Offset > 0) { |
+ Str << " + "; |
+ } |
+ Str << Offset; |
Karl
2016/02/03 21:03:05
This works, but is not obvious.
John
2016/02/03 21:25:20
Agreed, done.
|
+ } |
+ |
+ // We need to emit the '- .' for PCRel fixups. Even if the relocation kind() |
+ // is not PCRel, we emit the '- .' for the _GLOBAL_OFFSET_TABLE_. |
+ // TODO(jpp): create fixups wrt the GOT with the right fixup kind. |
+ if (Asm.fixupIsPCRel(kind()) || Symbol == GlobalOffsetTable) |
Str << " - ."; |
Str << "\n"; |
return FixupSize; |
} |
+void AssemblerFixup::emitOffset(Assembler *Asm) const { |
+ Asm->store(position(), offset()); |
+} |
+ |
size_t AssemblerTextFixup::emit(GlobalContext *Ctx, const Assembler &) const { |
Ctx->getStrEmit() << Message << "\n"; |
return NumBytes; |