#ifndef LLVM_MC_MCFIXUP_H
#define LLVM_MC_MCFIXUP_H
+#include "llvm/MC/MCExpr.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SMLoc.h"
#include <cassert>
namespace llvm {
-
-// Private constants, do not use.
-//
-// This is currently laid out so that the MCFixup fields can be efficiently
-// accessed, while keeping the offset field large enough that the assembler
-// backend can reasonably use the MCFixup representation for an entire fragment
-// (splitting any overly large fragments).
-//
-// The division of bits between the kind and the opindex can be tweaked if we
-// end up needing more bits for target dependent kinds.
-enum {
- MCFIXUP_NUM_GENERIC_KINDS = 128,
- MCFIXUP_NUM_KIND_BITS = 8,
- MCFIXUP_NUM_OPINDEX_BITS = 8,
- MCFIXUP_NUM_OFFSET_BITS = (32 - MCFIXUP_NUM_OPINDEX_BITS -
- MCFIXUP_NUM_OPINDEX_BITS)
-};
+class MCExpr;
/// MCFixupKind - Extensible enumeration to represent the type of a fixup.
enum MCFixupKind {
FK_Data_2, ///< A two-byte fixup.
FK_Data_4, ///< A four-byte fixup.
FK_Data_8, ///< A eight-byte fixup.
-
- FirstTargetFixupKind = MCFIXUP_NUM_GENERIC_KINDS,
-
- MaxTargetFixupKind = (1 << MCFIXUP_NUM_KIND_BITS)
+ FK_PCRel_1, ///< A one-byte pc relative fixup.
+ FK_PCRel_2, ///< A two-byte pc relative fixup.
+ FK_PCRel_4, ///< A four-byte pc relative fixup.
+ FK_PCRel_8, ///< A eight-byte pc relative fixup.
+ FK_GPRel_1, ///< A one-byte gp relative fixup.
+ FK_GPRel_2, ///< A two-byte gp relative fixup.
+ FK_GPRel_4, ///< A four-byte gp relative fixup.
+ FK_GPRel_8, ///< A eight-byte gp relative fixup.
+ FK_SecRel_1, ///< A one-byte section relative fixup.
+ FK_SecRel_2, ///< A two-byte section relative fixup.
+ FK_SecRel_4, ///< A four-byte section relative fixup.
+ FK_SecRel_8, ///< A eight-byte section relative fixup.
+
+ FirstTargetFixupKind = 128,
+
+ // Limit range of target fixups, in case we want to pack more efficiently
+ // later.
+ MaxTargetFixupKind = (1 << 8)
};
-/// MCFixup - Encode information on a single operation to perform on an byte
+/// MCFixup - Encode information on a single operation to perform on a byte
/// sequence (e.g., an encoded instruction) which requires assemble- or run-
/// time patching.
///
/// fixups become relocations in the object file (or errors, if the fixup cannot
/// be encoded on the target).
class MCFixup {
- static const unsigned MaxOffset = 1 << MCFIXUP_NUM_KIND_BITS;
+ /// The value to put into the fixup location. The exact interpretation of the
+ /// expression is target dependent, usually it will be one of the operands to
+ /// an instruction or an assembler directive.
+ const MCExpr *Value;
/// The byte index of start of the relocation inside the encoded instruction.
- unsigned Offset : MCFIXUP_NUM_OFFSET_BITS;
-
- /// The index of the operand to encode into the instruction.
- unsigned OpIndex : MCFIXUP_NUM_OPINDEX_BITS;
+ uint32_t Offset;
/// The target dependent kind of fixup item this is. The kind is used to
/// determine how the operand value should be encoded into the instruction.
- unsigned Kind : MCFIXUP_NUM_KIND_BITS;
+ unsigned Kind;
+ /// The source location which gave rise to the fixup, if any.
+ SMLoc Loc;
public:
- static MCFixup Create(unsigned Offset, unsigned OpIndex, MCFixupKind Kind) {
+ static MCFixup Create(uint32_t Offset, const MCExpr *Value,
+ MCFixupKind Kind, SMLoc Loc = SMLoc()) {
+ assert(unsigned(Kind) < MaxTargetFixupKind && "Kind out of range!");
MCFixup FI;
+ FI.Value = Value;
FI.Offset = Offset;
- FI.OpIndex = OpIndex;
FI.Kind = unsigned(Kind);
-
- assert(Offset == FI.Offset && "Offset out of range!");
- assert(OpIndex == FI.OpIndex && "Operand index out of range!");
- assert(Kind == FI.Kind && "Kind out of range!");
+ FI.Loc = Loc;
return FI;
}
- unsigned getOffset() const { return Offset; }
+ MCFixupKind getKind() const { return MCFixupKind(Kind); }
- unsigned getOpIndex() const { return OpIndex; }
+ uint32_t getOffset() const { return Offset; }
+ void setOffset(uint32_t Value) { Offset = Value; }
+
+ 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, bool isPCRel) {
+ switch (Size) {
+ default: llvm_unreachable("Invalid generic fixup size!");
+ case 1: return isPCRel ? FK_PCRel_1 : FK_Data_1;
+ case 2: return isPCRel ? FK_PCRel_2 : FK_Data_2;
+ case 4: return isPCRel ? FK_PCRel_4 : FK_Data_4;
+ case 8: return isPCRel ? FK_PCRel_8 : FK_Data_8;
+ }
+ }
- MCFixupKind getKind() const { return MCFixupKind(Kind); }
+ SMLoc getLoc() const { return Loc; }
};
} // End llvm namespace