OSDN Git Service

MC: First cut at MCFixup, for getting fixup/relocation information out of an MCCodeEm...
authorDaniel Dunbar <daniel@zuster.org>
Tue, 9 Feb 2010 22:59:55 +0000 (22:59 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Tue, 9 Feb 2010 22:59:55 +0000 (22:59 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95708 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCCodeEmitter.h
include/llvm/MC/MCFixup.h [new file with mode: 0644]
lib/MC/MCAsmStreamer.cpp
lib/MC/MCMachOStreamer.cpp
lib/Target/X86/X86CodeEmitter.cpp
lib/Target/X86/X86MCCodeEmitter.cpp

index ad42dc2..5565945 100644 (file)
 #ifndef LLVM_MC_MCCODEEMITTER_H
 #define LLVM_MC_MCCODEEMITTER_H
 
+#include "llvm/MC/MCFixup.h"
+
+#include <cassert>
+
 namespace llvm {
+class MCExpr;
 class MCInst;
 class raw_ostream;
+template<typename T> class SmallVectorImpl;
+
+/// MCFixupKindInfo - Target independent information on a fixup kind.
+struct MCFixupKindInfo {
+  /// A target specific name for the fixup kind. The names will be unique for
+  /// distinct kinds on any given target.
+  const char *Name;
+
+  /// The bit offset to write the relocation into.
+  //
+  // FIXME: These two fields are under-specified and not general enough, but it
+  // is covers many things, and is enough to let the AsmStreamer pretty-print
+  // the encoding.
+  unsigned TargetOffset;
+
+  /// The number of bits written by this fixup. The bits are assumed to be
+  /// contiguous.
+  unsigned TargetSize;
+};
 
 /// MCCodeEmitter - Generic instruction encoding interface.
 class MCCodeEmitter {
+private:
   MCCodeEmitter(const MCCodeEmitter &);   // DO NOT IMPLEMENT
   void operator=(const MCCodeEmitter &);  // DO NOT IMPLEMENT
 protected: // Can only create subclasses.
   MCCodeEmitter();
+
 public:
   virtual ~MCCodeEmitter();
 
+  /// @name Target Independent Fixup Information
+  /// @{
+
+  /// getNumFixupKinds - Get the number of target specific fixup kinds.
+  virtual unsigned getNumFixupKinds() const = 0;
+
+  /// getFixupKindInfo - Get information on a fixup kind.
+  virtual MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const = 0;
+
+  /// @}
+
   /// EncodeInstruction - Encode the given \arg Inst to bytes on the output
   /// stream \arg OS.
-  virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS) const = 0;
+  virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS,
+                                 SmallVectorImpl<MCFixup> &Fixups) const = 0;
 };
 
 } // End llvm namespace
diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h
new file mode 100644 (file)
index 0000000..da8e92e
--- /dev/null
@@ -0,0 +1,95 @@
+//===-- llvm/MC/MCFixup.h - Instruction Relocation and Patching -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCFIXUP_H
+#define LLVM_MC_MCFIXUP_H
+
+#include <cassert>
+
+namespace llvm {
+
+// Private constants, do not use.
+//
+// This is currently layed out so that the MCFixup fields can be efficiently
+// accessed, while keeping the offset field large enought 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)
+};
+
+/// MCFixupKind - Extensible enumeration to represent the type of a fixup.
+enum MCFixupKind {
+  FK_Data_1 = 0, ///< A one-byte fixup.
+  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)
+};
+
+/// MCFixup - Encode information on a single operation to perform on an byte
+/// sequence (e.g., an encoded instruction) which requires assemble- or run-
+/// time patching.
+///
+/// Fixups are used any time the target instruction encoder needs to represent
+/// some value in an instruction which is not yet concrete. The encoder will
+/// encode the instruction assuming the value is 0, and emit a fixup which
+/// communicates to the assembler backend how it should rewrite the encoded
+/// value.
+///
+/// During the process of relaxation, the assembler will apply fixups as
+/// symbolic values become concrete. When relaxation is complete, any remaining
+/// 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 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;
+
+  /// 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;
+
+public:
+  static MCFixup Create(unsigned Offset, unsigned OpIndex, MCFixupKind Kind) {
+    MCFixup FI;
+    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!");
+    return FI;
+  }
+
+  unsigned getOffset() const { return Offset; }
+
+  unsigned getOpIndex() const { return OpIndex; }
+
+  MCFixupKind getKind() const { return MCFixupKind(Kind); }
+};
+
+} // End llvm namespace
+
+#endif
index d2e4858..f3c636c 100644 (file)
@@ -535,8 +535,9 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
   // Show the encoding in a comment if we have a code emitter.
   if (Emitter) {
     SmallString<256> Code;
+    SmallVector<MCFixup, 4> Fixups;
     raw_svector_ostream VecOS(Code);
-    Emitter->EncodeInstruction(Inst, VecOS);
+    Emitter->EncodeInstruction(Inst, VecOS, Fixups);
     VecOS.flush();
 
     raw_ostream &OS = GetCommentOS();
index 40a21ad..99a819f 100644 (file)
@@ -366,9 +366,10 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) {
   CurSectionData->setHasInstructions(true);
 
   // FIXME: Relocations!
+  SmallVector<MCFixup, 4> Fixups;
   SmallString<256> Code;
   raw_svector_ostream VecOS(Code);
-  Emitter->EncodeInstruction(Inst, VecOS);
+  Emitter->EncodeInstruction(Inst, VecOS, Fixups);
   EmitBytes(VecOS.str(), 0);
 }
 
index 0cfb0cb..7ee2223 100644 (file)
@@ -944,6 +944,24 @@ public:
     delete DummyF;
   }
 
+  unsigned getNumFixupKinds() const {
+    return 5;
+  }
+
+  MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
+    static MCFixupKindInfo Infos[] = {
+      { "reloc_pcrel_word", 0, 4 * 8 },
+      { "reloc_picrel_word", 0, 4 * 8 },
+      { "reloc_absolute_word", 0, 4 * 8 },
+      { "reloc_absolute_word_sext", 0, 4 * 8 },
+      { "reloc_absolute_dword", 0, 8 * 8 }
+    };
+
+    assert(Kind >= FirstTargetFixupKind && Kind < MaxTargetFixupKind &&
+           "Invalid kind!");
+    return Infos[Kind - FirstTargetFixupKind];
+  }
+
   bool AddRegToInstr(const MCInst &MI, MachineInstr *Instr,
                      unsigned Start) const {
     if (Start + 1 > MI.getNumOperands())
@@ -997,7 +1015,8 @@ public:
             AddRegToInstr(MI, Instr, Start + 4));
   }
 
-  void EncodeInstruction(const MCInst &MI, raw_ostream &OS) const {
+  void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+                         SmallVectorImpl<MCFixup> &Fixups) const {
     // Don't look yet!
 
     // Convert the MCInst to a MachineInstr so we can (ab)use the regular
index 7e9130b..679abb3 100644 (file)
@@ -33,6 +33,24 @@ public:
   }
 
   ~X86MCCodeEmitter() {}
+
+  unsigned getNumFixupKinds() const {
+    return 5;
+  }
+
+  MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
+    static MCFixupKindInfo Infos[] = {
+      { "reloc_pcrel_word", 0, 4 * 8 },
+      { "reloc_picrel_word", 0, 4 * 8 },
+      { "reloc_absolute_word", 0, 4 * 8 },
+      { "reloc_absolute_word_sext", 0, 4 * 8 },
+      { "reloc_absolute_dword", 0, 8 * 8 }
+    };
+
+    assert(Kind >= FirstTargetFixupKind && Kind < MaxTargetFixupKind &&
+           "Invalid kind!");
+    return Infos[Kind - FirstTargetFixupKind];
+  }
   
   static unsigned GetX86RegNum(const MCOperand &MO) {
     return X86RegisterInfo::getX86RegNum(MO.getReg());
@@ -75,7 +93,8 @@ public:
                         unsigned RegOpcodeField, intptr_t PCAdj,
                         raw_ostream &OS) const;
   
-  void EncodeInstruction(const MCInst &MI, raw_ostream &OS) const;
+  void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+                         SmallVectorImpl<MCFixup> &Fixups) const;
   
 };
 
@@ -379,7 +398,8 @@ static unsigned DetermineREXPrefix(const MCInst &MI, unsigned TSFlags,
 }
 
 void X86MCCodeEmitter::
-EncodeInstruction(const MCInst &MI, raw_ostream &OS) const {
+EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+                  SmallVectorImpl<MCFixup> &Fixups) const {
   unsigned Opcode = MI.getOpcode();
   const TargetInstrDesc &Desc = TII.get(Opcode);
   unsigned TSFlags = Desc.TSFlags;