From e3d3572e282733bd7aa5ac14115ed0804174e426 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 7 Dec 2011 00:28:57 +0000 Subject: [PATCH] Add a few moreLocal/Global R_MIPS_GOT related fixups and make the addend fixup code a bit more generic Patch by Jack Carter. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@145998 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCExpr.h | 1 + include/llvm/Support/ELF.h | 1 + lib/MC/ELFObjectWriter.cpp | 3 +- .../Mips/InstPrinter/MipsInstPrinter.cpp | 1 + .../Mips/MCTargetDesc/MipsAsmBackend.cpp | 74 ++++++++----------- lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h | 3 +- lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h | 7 +- .../Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 5 +- lib/Target/Mips/MipsISelLowering.cpp | 2 +- lib/Target/Mips/MipsMCInstLower.cpp | 1 + 10 files changed, 50 insertions(+), 48 deletions(-) diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 3172fd75ce6..40359c49fc2 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -179,6 +179,7 @@ public: VK_Mips_None, VK_Mips_GPREL, VK_Mips_GOT_CALL, + VK_Mips_GOT16, VK_Mips_GOT, VK_Mips_ABS_HI, VK_Mips_ABS_LO, diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index a3906b1dbab..a81be552589 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -627,6 +627,7 @@ enum { R_MIPS_GPREL16 = 7, R_MIPS_LITERAL = 8, R_MIPS_GOT16 = 9, + R_MIPS_GOT = 9, R_MIPS_PC16 = 10, R_MIPS_CALL16 = 11, R_MIPS_GPREL32 = 12, diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 132e81788d8..935ef4209d4 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -1872,7 +1872,8 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, case Mips::fixup_Mips_CALL16: Type = ELF::R_MIPS_CALL16; break; - case Mips::fixup_Mips_GOT16: + case Mips::fixup_Mips_GOT_Global: + case Mips::fixup_Mips_GOT_Local: Type = ELF::R_MIPS_GOT16; break; case Mips::fixup_Mips_HI16: diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index f544d396289..469e73382f5 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -96,6 +96,7 @@ static void printExpr(const MCExpr *Expr, raw_ostream &OS) { case MCSymbolRefExpr::VK_None: break; case MCSymbolRefExpr::VK_Mips_GPREL: OS << "%gp_rel("; break; case MCSymbolRefExpr::VK_Mips_GOT_CALL: OS << "%call16("; break; + case MCSymbolRefExpr::VK_Mips_GOT16: OS << "%got("; break; case MCSymbolRefExpr::VK_Mips_GOT: OS << "%got("; break; case MCSymbolRefExpr::VK_Mips_ABS_HI: OS << "%hi("; break; case MCSymbolRefExpr::VK_Mips_ABS_LO: OS << "%lo("; break; diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 8a8e36add75..60ff4feba7a 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -29,13 +29,19 @@ #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" + using namespace llvm; +// Prepare value for the target space for it static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { // Add/subtract and shift switch (Kind) { default: + return 0; + case FK_GPRel_4: + case FK_Data_4: + case Mips::fixup_Mips_LO16: break; case Mips::fixup_Mips_PC16: // So far we are only using this type for branches. @@ -52,25 +58,10 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { // address range. Value >>= 2; break; - } - - // Mask off value for placement as an operand - switch (Kind) { - default: - break; - case FK_GPRel_4: - case FK_Data_4: - Value &= 0xffffffff; - break; - case Mips::fixup_Mips_26: - Value &= 0x03ffffff; - break; - case Mips::fixup_Mips_LO16: - case Mips::fixup_Mips_PC16: - Value &= 0x0000ffff; - break; case Mips::fixup_Mips_HI16: - Value >>= 16; + case Mips::fixup_Mips_GOT_Local: + // Get the higher 16-bits. Also add 1 if bit 15 is 1. + Value = (Value >> 16) + ((Value & 0x8000) != 0); break; } @@ -96,42 +87,40 @@ public: /// fixup kind as appropriate. void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { - unsigned Kind = (unsigned)Fixup.getKind(); - Value = adjustFixupValue(Kind, Value); + MCFixupKind Kind = Fixup.getKind(); + Value = adjustFixupValue((unsigned)Kind, Value); if (!Value) - return; // Doesn't change encoding. + return; // Doesn't change encoding. unsigned Offset = Fixup.getOffset(); - switch (Kind) { - default: - llvm_unreachable("Unknown fixup kind!"); - case Mips::fixup_Mips_GOT16: // This will be fixed up at link time - break; - case FK_GPRel_4: - case FK_Data_4: - case Mips::fixup_Mips_26: - case Mips::fixup_Mips_LO16: - case Mips::fixup_Mips_PC16: - case Mips::fixup_Mips_HI16: - // For each byte of the fragment that the fixup touches, mask i - // the fixup value. The Value has been "split up" into the appr - // bitfields above. - for (unsigned i = 0; i != 4; ++i) // FIXME - Need to support 2 and 8 bytes - Data[Offset + i] += uint8_t((Value >> (i * 8)) & 0xff); - break; + // FIXME: The below code will not work across endian models + // How many bytes/bits are we fixing up? + unsigned NumBytes = ((getFixupKindInfo(Kind).TargetSize-1)/8)+1; + uint64_t Mask = ((uint64_t)1 << getFixupKindInfo(Kind).TargetSize) - 1; + + // Grab current value, if any, from bits. + uint64_t CurVal = 0; + for (unsigned i = 0; i != NumBytes; ++i) + CurVal |= ((uint8_t)Data[Offset + i]) << (i * 8); + + CurVal = (CurVal & ~Mask) | ((CurVal + Value) & Mask); + + // Write out the bytes back to the code/data bits. + // First the unaffected bits and then the fixup. + for (unsigned i = 0; i != NumBytes; ++i) { + Data[Offset + i] = uint8_t((CurVal >> (i * 8)) & 0xff); } - } +} unsigned getNumFixupKinds() const { return Mips::NumTargetFixupKinds; } const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { const static MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] = { - // This table *must* be in the order that the fixup_* kinds a + // This table *must* be in same the order of fixup_* kinds in // MipsFixupKinds.h. // // name offset bits flags - { "fixup_Mips_NONE", 0, 0, 0 }, { "fixup_Mips_16", 0, 16, 0 }, { "fixup_Mips_32", 0, 32, 0 }, { "fixup_Mips_REL32", 0, 32, 0 }, @@ -140,7 +129,8 @@ public: { "fixup_Mips_LO16", 0, 16, 0 }, { "fixup_Mips_GPREL16", 0, 16, 0 }, { "fixup_Mips_LITERAL", 0, 16, 0 }, - { "fixup_Mips_GOT16", 0, 16, 0 }, + { "fixup_Mips_GOT_Global", 0, 16, 0 }, + { "fixup_Mips_GOT_Local", 0, 16, 0 }, { "fixup_Mips_PC16", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_Mips_CALL16", 0, 16, 0 }, { "fixup_Mips_GPREL32", 0, 32, 0 }, diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index 66c6f8ebdd5..be2815db051 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -31,8 +31,9 @@ namespace MipsII { MO_NO_FLAG, - /// MO_GOT - Represents the offset into the global offset table at which + /// MO_GOT16 - Represents the offset into the global offset table at which /// the address the relocation entry symbol resides during execution. + MO_GOT16, MO_GOT, /// MO_GOT_CALL - Represents the offset into the global offset table at diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index 20890ed2327..d118656b62d 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -42,8 +42,11 @@ namespace Mips { // fixup_Mips_xxx - R_MIPS_LITERAL. fixup_Mips_LITERAL, - // fixup_Mips_xxx - R_MIPS_GOT16. - fixup_Mips_GOT16, + // Global symbol fixup resulting in - R_MIPS_GOT16. + fixup_Mips_GOT_Global, + + // Local symbol fixup resulting in - R_MIPS_GOT16. + fixup_Mips_GOT_Local, // fixup_Mips_xxx - R_MIPS_PC16. fixup_Mips_PC16, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 0c3cbb31d51..89a39deb9de 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -194,8 +194,11 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, case MCSymbolRefExpr::VK_Mips_GOT_CALL: FixupKind = Mips::fixup_Mips_CALL16; break; + case MCSymbolRefExpr::VK_Mips_GOT16: + FixupKind = Mips::fixup_Mips_GOT_Global; + break; case MCSymbolRefExpr::VK_Mips_GOT: - FixupKind = Mips::fixup_Mips_GOT16; + FixupKind = Mips::fixup_Mips_GOT_Local; break; case MCSymbolRefExpr::VK_Mips_ABS_HI: FixupKind = Mips::fixup_Mips_HI16; diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 272b8c57f2f..12b5dbf6539 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -1488,7 +1488,7 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, (GV->hasLocalLinkage() && !isa(GV))); unsigned GotFlag = IsN64 ? (HasGotOfst ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT_DISP) : - MipsII::MO_GOT; + (HasGotOfst ? MipsII::MO_GOT : MipsII::MO_GOT16); SDValue GA = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0, GotFlag); GA = DAG.getNode(MipsISD::WrapperPIC, dl, ValTy, GA); SDValue ResNode = DAG.getLoad(ValTy, dl, diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index 6fc2af1a771..81812919ec5 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -41,6 +41,7 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, case MipsII::MO_NO_FLAG: Kind = MCSymbolRefExpr::VK_None; break; case MipsII::MO_GPREL: Kind = MCSymbolRefExpr::VK_Mips_GPREL; break; case MipsII::MO_GOT_CALL: Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break; + case MipsII::MO_GOT16: Kind = MCSymbolRefExpr::VK_Mips_GOT16; break; case MipsII::MO_GOT: Kind = MCSymbolRefExpr::VK_Mips_GOT; break; case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break; case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break;