1205407Srdivacky//===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===// 2205407Srdivacky// 3205407Srdivacky// The LLVM Compiler Infrastructure 4205407Srdivacky// 5205407Srdivacky// This file is distributed under the University of Illinois Open Source 6205407Srdivacky// License. See LICENSE.TXT for details. 7205407Srdivacky// 8205407Srdivacky//===----------------------------------------------------------------------===// 9205407Srdivacky 10205407Srdivacky#ifndef LLVM_MC_MCOBJECTWRITER_H 11205407Srdivacky#define LLVM_MC_MCOBJECTWRITER_H 12205407Srdivacky 13249423Sdim#include "llvm/ADT/SmallVector.h" 14243830Sdim#include "llvm/Support/Compiler.h" 15218893Sdim#include "llvm/Support/DataTypes.h" 16249423Sdim#include "llvm/Support/raw_ostream.h" 17205407Srdivacky#include <cassert> 18205407Srdivacky 19205407Srdivackynamespace llvm { 20206083Srdivackyclass MCAsmLayout; 21205407Srdivackyclass MCAssembler; 22208599Srdivackyclass MCFixup; 23206083Srdivackyclass MCFragment; 24218893Sdimclass MCSymbolData; 25218893Sdimclass MCSymbolRefExpr; 26205407Srdivackyclass MCValue; 27205407Srdivacky 28205407Srdivacky/// MCObjectWriter - Defines the object file and target independent interfaces 29205407Srdivacky/// used by the assembler backend to write native file format object files. 30205407Srdivacky/// 31205407Srdivacky/// The object writer contains a few callbacks used by the assembler to allow 32205407Srdivacky/// the object writer to modify the assembler data structures at appropriate 33205407Srdivacky/// points. Once assembly is complete, the object writer is given the 34205407Srdivacky/// MCAssembler instance, which contains all the symbol and section data which 35205407Srdivacky/// should be emitted as part of WriteObject(). 36205407Srdivacky/// 37205407Srdivacky/// The object writer also contains a number of helper methods for writing 38205407Srdivacky/// binary data to the output stream. 39205407Srdivackyclass MCObjectWriter { 40243830Sdim MCObjectWriter(const MCObjectWriter &) LLVM_DELETED_FUNCTION; 41243830Sdim void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION; 42205407Srdivacky 43205407Srdivackyprotected: 44205407Srdivacky raw_ostream &OS; 45205407Srdivacky 46205407Srdivacky unsigned IsLittleEndian : 1; 47205407Srdivacky 48205407Srdivackyprotected: // Can only create subclasses. 49205407Srdivacky MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian) 50205407Srdivacky : OS(_OS), IsLittleEndian(_IsLittleEndian) {} 51205407Srdivacky 52205407Srdivackypublic: 53205407Srdivacky virtual ~MCObjectWriter(); 54205407Srdivacky 55249423Sdim /// lifetime management 56249423Sdim virtual void reset() { } 57249423Sdim 58207618Srdivacky bool isLittleEndian() const { return IsLittleEndian; } 59205407Srdivacky 60205407Srdivacky raw_ostream &getStream() { return OS; } 61205407Srdivacky 62205407Srdivacky /// @name High-Level API 63205407Srdivacky /// @{ 64205407Srdivacky 65249423Sdim /// \brief Perform any late binding of symbols (for example, to assign symbol 66249423Sdim /// indices for use when generating relocations). 67205407Srdivacky /// 68205407Srdivacky /// This routine is called by the assembler after layout and relaxation is 69205407Srdivacky /// complete. 70218893Sdim virtual void ExecutePostLayoutBinding(MCAssembler &Asm, 71218893Sdim const MCAsmLayout &Layout) = 0; 72205407Srdivacky 73249423Sdim /// \brief Record a relocation entry. 74205407Srdivacky /// 75205407Srdivacky /// This routine is called by the assembler after layout and relaxation, and 76205407Srdivacky /// post layout binding. The implementation is responsible for storing 77205407Srdivacky /// information about the relocation so that it can be emitted during 78205407Srdivacky /// WriteObject(). 79205407Srdivacky virtual void RecordRelocation(const MCAssembler &Asm, 80206083Srdivacky const MCAsmLayout &Layout, 81206083Srdivacky const MCFragment *Fragment, 82208599Srdivacky const MCFixup &Fixup, MCValue Target, 83205407Srdivacky uint64_t &FixedValue) = 0; 84205407Srdivacky 85218893Sdim /// \brief Check whether the difference (A - B) between two symbol 86218893Sdim /// references is fully resolved. 87218893Sdim /// 88218893Sdim /// Clients are not required to answer precisely and may conservatively return 89218893Sdim /// false, even when a difference is fully resolved. 90218893Sdim bool 91218893Sdim IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, 92218893Sdim const MCSymbolRefExpr *A, 93218893Sdim const MCSymbolRefExpr *B, 94218893Sdim bool InSet) const; 95218893Sdim 96218893Sdim virtual bool 97218893Sdim IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, 98218893Sdim const MCSymbolData &DataA, 99218893Sdim const MCFragment &FB, 100218893Sdim bool InSet, 101218893Sdim bool IsPCRel) const; 102218893Sdim 103249423Sdim /// \brief Write the object file. 104205407Srdivacky /// 105205407Srdivacky /// This routine is called by the assembler after layout and relaxation is 106208599Srdivacky /// complete, fixups have been evaluated and applied, and relocations 107205407Srdivacky /// generated. 108218893Sdim virtual void WriteObject(MCAssembler &Asm, 109206083Srdivacky const MCAsmLayout &Layout) = 0; 110205407Srdivacky 111205407Srdivacky /// @} 112205407Srdivacky /// @name Binary Output 113205407Srdivacky /// @{ 114205407Srdivacky 115205407Srdivacky void Write8(uint8_t Value) { 116205407Srdivacky OS << char(Value); 117205407Srdivacky } 118205407Srdivacky 119205407Srdivacky void WriteLE16(uint16_t Value) { 120205407Srdivacky Write8(uint8_t(Value >> 0)); 121205407Srdivacky Write8(uint8_t(Value >> 8)); 122205407Srdivacky } 123205407Srdivacky 124205407Srdivacky void WriteLE32(uint32_t Value) { 125205407Srdivacky WriteLE16(uint16_t(Value >> 0)); 126205407Srdivacky WriteLE16(uint16_t(Value >> 16)); 127205407Srdivacky } 128205407Srdivacky 129205407Srdivacky void WriteLE64(uint64_t Value) { 130205407Srdivacky WriteLE32(uint32_t(Value >> 0)); 131205407Srdivacky WriteLE32(uint32_t(Value >> 32)); 132205407Srdivacky } 133205407Srdivacky 134205407Srdivacky void WriteBE16(uint16_t Value) { 135205407Srdivacky Write8(uint8_t(Value >> 8)); 136205407Srdivacky Write8(uint8_t(Value >> 0)); 137205407Srdivacky } 138205407Srdivacky 139205407Srdivacky void WriteBE32(uint32_t Value) { 140205407Srdivacky WriteBE16(uint16_t(Value >> 16)); 141205407Srdivacky WriteBE16(uint16_t(Value >> 0)); 142205407Srdivacky } 143205407Srdivacky 144205407Srdivacky void WriteBE64(uint64_t Value) { 145205407Srdivacky WriteBE32(uint32_t(Value >> 32)); 146205407Srdivacky WriteBE32(uint32_t(Value >> 0)); 147205407Srdivacky } 148205407Srdivacky 149205407Srdivacky void Write16(uint16_t Value) { 150205407Srdivacky if (IsLittleEndian) 151205407Srdivacky WriteLE16(Value); 152205407Srdivacky else 153205407Srdivacky WriteBE16(Value); 154205407Srdivacky } 155205407Srdivacky 156205407Srdivacky void Write32(uint32_t Value) { 157205407Srdivacky if (IsLittleEndian) 158205407Srdivacky WriteLE32(Value); 159205407Srdivacky else 160205407Srdivacky WriteBE32(Value); 161205407Srdivacky } 162205407Srdivacky 163205407Srdivacky void Write64(uint64_t Value) { 164205407Srdivacky if (IsLittleEndian) 165205407Srdivacky WriteLE64(Value); 166205407Srdivacky else 167205407Srdivacky WriteBE64(Value); 168205407Srdivacky } 169205407Srdivacky 170205407Srdivacky void WriteZeros(unsigned N) { 171205407Srdivacky const char Zeros[16] = { 0 }; 172205407Srdivacky 173205407Srdivacky for (unsigned i = 0, e = N / 16; i != e; ++i) 174205407Srdivacky OS << StringRef(Zeros, 16); 175205407Srdivacky 176205407Srdivacky OS << StringRef(Zeros, N % 16); 177205407Srdivacky } 178205407Srdivacky 179249423Sdim void WriteBytes(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) { 180249423Sdim WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize); 181249423Sdim } 182249423Sdim 183205407Srdivacky void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) { 184249423Sdim // TODO: this version may need to go away once all fragment contents are 185249423Sdim // converted to SmallVector<char, N> 186208599Srdivacky assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) && 187208599Srdivacky "data size greater than fill size, unexpected large write will occur"); 188205407Srdivacky OS << Str; 189205407Srdivacky if (ZeroFillSize) 190205407Srdivacky WriteZeros(ZeroFillSize - Str.size()); 191205407Srdivacky } 192205407Srdivacky 193205407Srdivacky /// @} 194218893Sdim 195205407Srdivacky}; 196205407Srdivacky 197205407Srdivacky} // End llvm namespace 198205407Srdivacky 199205407Srdivacky#endif 200