|  | //===- subzero/src/IceFixups.cpp - Implementation of Assembler Fixups -----===// | 
|  | // | 
|  | //                        The Subzero Code Generator | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// \brief Implements the AssemblerFixup class, a very basic target-independent | 
|  | /// representation of a fixup or relocation. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "IceFixups.h" | 
|  |  | 
|  | #include "IceOperand.h" | 
|  |  | 
|  | namespace Ice { | 
|  |  | 
|  | const Constant *AssemblerFixup::NullSymbol = nullptr; | 
|  |  | 
|  | RelocOffsetT AssemblerFixup::offset() const { | 
|  | if (isNullSymbol()) | 
|  | return addend_; | 
|  | if (!ValueIsSymbol) { | 
|  | if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(ConstValue)) | 
|  | return CR->getOffset() + addend_; | 
|  | } | 
|  | return addend_; | 
|  | } | 
|  |  | 
|  | GlobalString AssemblerFixup::symbol() const { | 
|  | assert(!isNullSymbol()); | 
|  | assert(!ValueIsSymbol); | 
|  | const Constant *C = ConstValue; | 
|  | if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(C)) { | 
|  | return CR->getName(); | 
|  | } | 
|  | // NOTE: currently only float/doubles are put into constant pools. In the | 
|  | // future we may put integers as well. | 
|  | assert(llvm::isa<ConstantFloat>(C) || llvm::isa<ConstantDouble>(C)); | 
|  | return C->getLabelName(); | 
|  | } | 
|  |  | 
|  | size_t AssemblerFixup::emit(GlobalContext *Ctx, const Assembler &Asm) const { | 
|  | static constexpr const size_t FixupSize = 4; | 
|  | if (!BuildDefs::dump()) | 
|  | return FixupSize; | 
|  | Ostream &Str = Ctx->getStrEmit(); | 
|  | Str << "\t.long "; | 
|  | std::string Symbol; | 
|  | if (isNullSymbol()) { | 
|  | Str << "__Sz_AbsoluteZero"; | 
|  | } else { | 
|  | Symbol = symbol().toString(); | 
|  | Str << Symbol; | 
|  | assert(!ValueIsSymbol); | 
|  | if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(ConstValue)) { | 
|  | if (!Asm.fixupIsPCRel(kind()) && getFlags().getUseNonsfi() && | 
|  | CR->getName().toString() != GlobalOffsetTable) { | 
|  | Str << "@GOTOFF"; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | assert(Asm.load<RelocOffsetT>(position()) == 0); | 
|  |  | 
|  | RelocOffsetT Offset = offset(); | 
|  | if (Offset != 0) { | 
|  | if (Offset > 0) { | 
|  | Str << " + " << Offset; | 
|  | } else { | 
|  | assert(Offset != std::numeric_limits<RelocOffsetT>::lowest()); | 
|  | Str << " - " << -Offset; | 
|  | } | 
|  | } | 
|  |  | 
|  | // We need to emit the '- .' for PCRel fixups. Even if the relocation kind() | 
|  | // is not PCRel, we emit the '- .' for the _GLOBAL_OFFSET_TABLE_. | 
|  | // TODO(jpp): create fixups wrt the GOT with the right fixup kind. | 
|  | if (Asm.fixupIsPCRel(kind()) || Symbol == GlobalOffsetTable) | 
|  | Str << " - ."; | 
|  | Str << "\n"; | 
|  | return FixupSize; | 
|  | } | 
|  |  | 
|  | void AssemblerFixup::emitOffset(Assembler *Asm) const { | 
|  | Asm->store(position(), offset()); | 
|  | } | 
|  |  | 
|  | size_t AssemblerTextFixup::emit(GlobalContext *Ctx, const Assembler &) const { | 
|  | Ctx->getStrEmit() << Message << "\n"; | 
|  | return NumBytes; | 
|  | } | 
|  |  | 
|  | } // end of namespace Ice |