diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 268a3fc3b8d..4527f3c28d3 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -14,6 +14,7 @@ #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" #include "llvm/Support/Casting.h" +#include "llvm/MC/MCFixup.h" #include "llvm/System/DataTypes.h" #include // FIXME: Shouldn't be needed. @@ -37,8 +38,8 @@ struct MCAsmFixup { /// Value - The expression to eventually write into the fragment. const MCExpr *Value; - /// Size - The fixup size. - unsigned Size; + /// Kind - The fixup kind. + MCFixupKind Kind; /// FixedValue - The value to replace the fix up by. // @@ -46,8 +47,8 @@ struct MCAsmFixup { uint64_t FixedValue; public: - MCAsmFixup(uint64_t _Offset, const MCExpr &_Value, unsigned _Size) - : Offset(_Offset), Value(&_Value), Size(_Size), FixedValue(0) {} + MCAsmFixup(uint64_t _Offset, const MCExpr &_Value, MCFixupKind _Kind) + : Offset(_Offset), Value(&_Value), Kind(_Kind), FixedValue(0) {} }; class MCFragment : public ilist_node { diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h index f325d655001..cd0dd1962ae 100644 --- a/include/llvm/MC/MCFixup.h +++ b/include/llvm/MC/MCFixup.h @@ -89,6 +89,18 @@ public: unsigned getOffset() const { return Offset; } const MCExpr *getValue() const { return Value; } + + /// getKindForSize - Return the generic fixup kind for a value with the given + /// size. It is an error to pass an unsupported size. + static MCFixupKind getKindForSize(unsigned Size) { + switch (Size) { + default: assert(0 && "Invalid generic fixup size!"); + case 1: return FK_Data_1; + case 2: return FK_Data_2; + case 4: return FK_Data_4; + case 8: return FK_Data_8; + } + } }; } // End llvm namespace diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 2875730dd32..b2c4112f484 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -47,6 +47,16 @@ static bool isVirtualSection(const MCSection &Section) { return (Type == MCSectionMachO::S_ZEROFILL); } +static unsigned getFixupKindLog2Size(MCFixupKind Kind) { + switch (Kind) { + default: llvm_unreachable("invalid fixup kind!"); + case FK_Data_1: return 0; + case FK_Data_2: return 1; + case FK_Data_4: return 2; + case FK_Data_8: return 3; + } +} + class MachObjectWriter { // See . enum { @@ -426,8 +436,7 @@ public: Value2 = SD->getFragment()->getAddress() + SD->getOffset(); } - unsigned Log2Size = Log2_32(Fixup.Size); - assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!"); + unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind); // The value which goes in the fixup is current value of the expression. Fixup.FixedValue = Value - Value2 + Target.getConstant(); @@ -512,8 +521,7 @@ public: // The value which goes in the fixup is current value of the expression. Fixup.FixedValue = Value + Target.getConstant(); - unsigned Log2Size = Log2_32(Fixup.Size); - assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!"); + unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind); // struct relocation_info (8 bytes) MachRelocationEntry MRE; @@ -880,8 +888,12 @@ public: } void ApplyFixup(const MCAsmFixup &Fixup, MCDataFragment &DF) { + unsigned Size = 1 << getFixupKindLog2Size(Fixup.Kind); + // FIXME: Endianness assumption. - for (unsigned i = 0; i != Fixup.Size; ++i) + assert(Fixup.Offset + Size <= DF.getContents().size() && + "Invalid fixup offset!"); + for (unsigned i = 0; i != Size; ++i) DF.getContents()[Fixup.Offset + i] = uint8_t(Fixup.FixedValue >> (i * 8)); } }; @@ -1186,8 +1198,8 @@ void MCAssembler::Finish() { namespace llvm { raw_ostream &operator<<(raw_ostream &OS, const MCAsmFixup &AF) { - OS << ""; + OS << ""; return OS; } @@ -1224,7 +1236,7 @@ void MCDataFragment::dump() { if (i) OS << ","; OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF); } - OS << "]"; + OS << "] (" << getContents().size() << " bytes)"; if (!getFixups().empty()) { OS << ",\n "; diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 770105d0e51..1801170ea03 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -347,7 +347,8 @@ void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size, DF->getContents().push_back(uint8_t(AbsValue >> (i * 8))); } else { DF->getFixups().push_back(MCAsmFixup(DF->getContents().size(), - *AddValueSymbols(Value), Size)); + *AddValueSymbols(Value), + MCFixup::getKindForSize(Size))); DF->getContents().resize(DF->getContents().size() + Size, 0); } }