| //===- subzero/src/IceFixups.h - Assembler fixup kinds ----------*- C++ -*-===// | |
| // | |
| // The Subzero Code Generator | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| /// | |
| /// \file | |
| /// \brief Declares generic fixup types. | |
| /// | |
| //===----------------------------------------------------------------------===// | |
| #ifndef SUBZERO_SRC_ICEFIXUPS_H | |
| #define SUBZERO_SRC_ICEFIXUPS_H | |
| #include "IceClFlags.h" | |
| #include "IceDefs.h" | |
| #include "IceStringPool.h" | |
| namespace Ice { | |
| /// Each target and container format has a different namespace of relocations. | |
| /// This holds the specific target+container format's relocation number. | |
| using FixupKind = uint32_t; | |
| struct ELFSym; | |
| /// Assembler fixups are positions in generated code/data that hold relocation | |
| /// information that needs to be processed before finalizing the code/data. | |
| class AssemblerFixup { | |
| AssemblerFixup &operator=(const AssemblerFixup &) = delete; | |
| public: | |
| AssemblerFixup() = default; | |
| AssemblerFixup(const AssemblerFixup &) = default; | |
| virtual ~AssemblerFixup() = default; | |
| intptr_t position() const { return position_; } | |
| void set_position(intptr_t Position) { position_ = Position; } | |
| FixupKind kind() const { return kind_; } | |
| void set_kind(FixupKind Kind) { kind_ = Kind; } | |
| RelocOffsetT offset() const; | |
| GlobalString symbol() const; | |
| static const Constant *NullSymbol; | |
| bool isNullSymbol() const { return ConstValue == NullSymbol; } | |
| static constexpr AssemblerFixup *NoFixup = nullptr; | |
| bool valueIsSymbol() const { return ValueIsSymbol; } | |
| void set_value(const Constant *Value) { | |
| ValueIsSymbol = false; | |
| ConstValue = Value; | |
| } | |
| void set_value(const ELFSym *Value) { | |
| ValueIsSymbol = true; | |
| SymbolValue = Value; | |
| } | |
| const ELFSym *getSymbolValue() const { | |
| assert(ValueIsSymbol); | |
| return SymbolValue; | |
| } | |
| void set_addend(RelocOffsetT Addend) { addend_ = Addend; } | |
| RelocOffsetT get_addend() const { return addend_; } | |
| /// Emits fixup, then returns the number of bytes to skip. | |
| virtual size_t emit(GlobalContext *Ctx, const Assembler &Asm) const; | |
| /// Emits offset() (little endian) in position_. If your fixup requires | |
| /// something smarter, you must create your own fixup type. | |
| virtual void emitOffset(Assembler *Asm) const; | |
| private: | |
| intptr_t position_ = 0; | |
| FixupKind kind_ = 0; | |
| // An offset addend to the fixup offset (as returned by offset()), in case the | |
| // assembler needs to adjust it. | |
| RelocOffsetT addend_ = 0; | |
| // Tagged union that holds either a Constant or ELFSym pointer, depending on | |
| // the ValueIsSymbol tag. | |
| bool ValueIsSymbol = false; | |
| union { | |
| const Constant *ConstValue; | |
| const ELFSym *SymbolValue; | |
| }; | |
| }; | |
| /// Extends a fixup to be textual. That is, it emits text instead of a sequence | |
| /// of bytes. This class is used as a fallback for unimplemented emitIAS | |
| /// methods, allowing them to generate compilable assembly code. | |
| class AssemblerTextFixup : public AssemblerFixup { | |
| AssemblerTextFixup() = delete; | |
| AssemblerTextFixup(const AssemblerTextFixup &) = delete; | |
| AssemblerTextFixup &operator=(const AssemblerTextFixup &) = delete; | |
| public: | |
| AssemblerTextFixup(const std::string &Message, size_t NumBytes) | |
| : AssemblerFixup(), Message(Message), NumBytes(NumBytes) {} | |
| ~AssemblerTextFixup() = default; | |
| size_t emit(GlobalContext *Ctx, const Assembler &Asm) const override; | |
| private: | |
| const std::string Message; | |
| const size_t NumBytes; | |
| }; | |
| using FixupList = std::vector<AssemblerFixup>; | |
| using FixupRefList = std::vector<AssemblerFixup *>; | |
| } // end of namespace Ice | |
| #endif // SUBZERO_SRC_ICEFIXUPS_H |