//===- 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