MCObjectWriter.h revision 309124
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" 16288943Sdim#include "llvm/Support/EndianStream.h" 17249423Sdim#include "llvm/Support/raw_ostream.h" 18205407Srdivacky#include <cassert> 19205407Srdivacky 20205407Srdivackynamespace llvm { 21206083Srdivackyclass MCAsmLayout; 22205407Srdivackyclass MCAssembler; 23208599Srdivackyclass MCFixup; 24206083Srdivackyclass MCFragment; 25309124Sdimclass MCSymbol; 26218893Sdimclass MCSymbolRefExpr; 27205407Srdivackyclass MCValue; 28205407Srdivacky 29288943Sdim/// Defines the object file and target independent interfaces used by the 30288943Sdim/// assembler backend to write native file format object files. 31205407Srdivacky/// 32205407Srdivacky/// The object writer contains a few callbacks used by the assembler to allow 33205407Srdivacky/// the object writer to modify the assembler data structures at appropriate 34205407Srdivacky/// points. Once assembly is complete, the object writer is given the 35205407Srdivacky/// MCAssembler instance, which contains all the symbol and section data which 36288943Sdim/// should be emitted as part of writeObject(). 37205407Srdivacky/// 38205407Srdivacky/// The object writer also contains a number of helper methods for writing 39205407Srdivacky/// binary data to the output stream. 40205407Srdivackyclass MCObjectWriter { 41288943Sdim MCObjectWriter(const MCObjectWriter &) = delete; 42288943Sdim void operator=(const MCObjectWriter &) = delete; 43205407Srdivacky 44296417Sdim raw_pwrite_stream *OS; 45296417Sdim 46205407Srdivackyprotected: 47205407Srdivacky unsigned IsLittleEndian : 1; 48205407Srdivacky 49205407Srdivackyprotected: // Can only create subclasses. 50288943Sdim MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian) 51296417Sdim : OS(&OS), IsLittleEndian(IsLittleEndian) {} 52205407Srdivacky 53296417Sdim unsigned getInitialOffset() { 54296417Sdim return OS->tell(); 55296417Sdim } 56296417Sdim 57205407Srdivackypublic: 58205407Srdivacky virtual ~MCObjectWriter(); 59205407Srdivacky 60249423Sdim /// lifetime management 61288943Sdim virtual void reset() {} 62249423Sdim 63207618Srdivacky bool isLittleEndian() const { return IsLittleEndian; } 64205407Srdivacky 65296417Sdim raw_pwrite_stream &getStream() { return *OS; } 66296417Sdim void setStream(raw_pwrite_stream &NewOS) { OS = &NewOS; } 67205407Srdivacky 68288943Sdim /// \name High-Level API 69205407Srdivacky /// @{ 70205407Srdivacky 71288943Sdim /// Perform any late binding of symbols (for example, to assign symbol 72249423Sdim /// indices for use when generating relocations). 73205407Srdivacky /// 74205407Srdivacky /// This routine is called by the assembler after layout and relaxation is 75205407Srdivacky /// complete. 76288943Sdim virtual void executePostLayoutBinding(MCAssembler &Asm, 77218893Sdim const MCAsmLayout &Layout) = 0; 78205407Srdivacky 79288943Sdim /// Record a relocation entry. 80205407Srdivacky /// 81205407Srdivacky /// This routine is called by the assembler after layout and relaxation, and 82205407Srdivacky /// post layout binding. The implementation is responsible for storing 83205407Srdivacky /// information about the relocation so that it can be emitted during 84288943Sdim /// writeObject(). 85288943Sdim virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, 86206083Srdivacky const MCFragment *Fragment, 87208599Srdivacky const MCFixup &Fixup, MCValue Target, 88288943Sdim bool &IsPCRel, uint64_t &FixedValue) = 0; 89205407Srdivacky 90288943Sdim /// Check whether the difference (A - B) between two symbol references is 91288943Sdim /// fully resolved. 92218893Sdim /// 93218893Sdim /// Clients are not required to answer precisely and may conservatively return 94218893Sdim /// false, even when a difference is fully resolved. 95288943Sdim bool isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, 96288943Sdim const MCSymbolRefExpr *A, 97288943Sdim const MCSymbolRefExpr *B, 98288943Sdim bool InSet) const; 99218893Sdim 100288943Sdim virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, 101296417Sdim const MCSymbol &A, 102296417Sdim const MCSymbol &B, 103296417Sdim bool InSet) const; 104296417Sdim 105296417Sdim virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, 106288943Sdim const MCSymbol &SymA, 107288943Sdim const MCFragment &FB, 108288943Sdim bool InSet, 109288943Sdim bool IsPCRel) const; 110218893Sdim 111288943Sdim /// True if this symbol (which is a variable) is weak. This is not 112288943Sdim /// just STB_WEAK, but more generally whether or not we can evaluate 113288943Sdim /// past it. 114288943Sdim virtual bool isWeak(const MCSymbol &Sym) const; 115288943Sdim 116288943Sdim /// Write the object file. 117205407Srdivacky /// 118205407Srdivacky /// This routine is called by the assembler after layout and relaxation is 119208599Srdivacky /// complete, fixups have been evaluated and applied, and relocations 120205407Srdivacky /// generated. 121288943Sdim virtual void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0; 122205407Srdivacky 123205407Srdivacky /// @} 124288943Sdim /// \name Binary Output 125205407Srdivacky /// @{ 126205407Srdivacky 127296417Sdim void write8(uint8_t Value) { *OS << char(Value); } 128205407Srdivacky 129288943Sdim void writeLE16(uint16_t Value) { 130296417Sdim support::endian::Writer<support::little>(*OS).write(Value); 131205407Srdivacky } 132205407Srdivacky 133288943Sdim void writeLE32(uint32_t Value) { 134296417Sdim support::endian::Writer<support::little>(*OS).write(Value); 135205407Srdivacky } 136205407Srdivacky 137288943Sdim void writeLE64(uint64_t Value) { 138296417Sdim support::endian::Writer<support::little>(*OS).write(Value); 139205407Srdivacky } 140205407Srdivacky 141288943Sdim void writeBE16(uint16_t Value) { 142296417Sdim support::endian::Writer<support::big>(*OS).write(Value); 143205407Srdivacky } 144205407Srdivacky 145288943Sdim void writeBE32(uint32_t Value) { 146296417Sdim support::endian::Writer<support::big>(*OS).write(Value); 147205407Srdivacky } 148205407Srdivacky 149288943Sdim void writeBE64(uint64_t Value) { 150296417Sdim support::endian::Writer<support::big>(*OS).write(Value); 151205407Srdivacky } 152205407Srdivacky 153288943Sdim void write16(uint16_t Value) { 154205407Srdivacky if (IsLittleEndian) 155288943Sdim writeLE16(Value); 156205407Srdivacky else 157288943Sdim writeBE16(Value); 158205407Srdivacky } 159205407Srdivacky 160288943Sdim void write32(uint32_t Value) { 161205407Srdivacky if (IsLittleEndian) 162288943Sdim writeLE32(Value); 163205407Srdivacky else 164288943Sdim writeBE32(Value); 165205407Srdivacky } 166205407Srdivacky 167288943Sdim void write64(uint64_t Value) { 168205407Srdivacky if (IsLittleEndian) 169288943Sdim writeLE64(Value); 170205407Srdivacky else 171288943Sdim writeBE64(Value); 172205407Srdivacky } 173205407Srdivacky 174205407Srdivacky void WriteZeros(unsigned N) { 175288943Sdim const char Zeros[16] = {0}; 176205407Srdivacky 177205407Srdivacky for (unsigned i = 0, e = N / 16; i != e; ++i) 178296417Sdim *OS << StringRef(Zeros, 16); 179205407Srdivacky 180296417Sdim *OS << StringRef(Zeros, N % 16); 181205407Srdivacky } 182205407Srdivacky 183288943Sdim void writeBytes(const SmallVectorImpl<char> &ByteVec, 184288943Sdim unsigned ZeroFillSize = 0) { 185288943Sdim writeBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize); 186249423Sdim } 187249423Sdim 188288943Sdim void writeBytes(StringRef Str, unsigned ZeroFillSize = 0) { 189249423Sdim // TODO: this version may need to go away once all fragment contents are 190249423Sdim // converted to SmallVector<char, N> 191288943Sdim assert( 192288943Sdim (ZeroFillSize == 0 || Str.size() <= ZeroFillSize) && 193288943Sdim "data size greater than fill size, unexpected large write will occur"); 194296417Sdim *OS << Str; 195205407Srdivacky if (ZeroFillSize) 196205407Srdivacky WriteZeros(ZeroFillSize - Str.size()); 197205407Srdivacky } 198205407Srdivacky 199205407Srdivacky /// @} 200205407Srdivacky}; 201205407Srdivacky 202205407Srdivacky} // End llvm namespace 203205407Srdivacky 204205407Srdivacky#endif 205