Chromium Code Reviews| 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; |