2010-03-19 09:28:59 +00:00
|
|
|
//===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_MC_MCOBJECTWRITER_H
|
|
|
|
#define LLVM_MC_MCOBJECTWRITER_H
|
|
|
|
|
2013-01-31 12:12:40 +00:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2012-08-29 06:28:46 +00:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2010-11-29 18:16:10 +00:00
|
|
|
#include "llvm/Support/DataTypes.h"
|
2012-12-03 17:02:12 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2010-03-19 09:28:59 +00:00
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
namespace llvm {
|
2010-03-24 03:43:40 +00:00
|
|
|
class MCAsmLayout;
|
2010-03-19 09:28:59 +00:00
|
|
|
class MCAssembler;
|
2010-05-26 15:18:56 +00:00
|
|
|
class MCFixup;
|
2010-03-22 20:35:50 +00:00
|
|
|
class MCFragment;
|
2010-12-24 21:22:02 +00:00
|
|
|
class MCSymbolData;
|
2010-12-17 04:54:54 +00:00
|
|
|
class MCSymbolRefExpr;
|
2010-03-19 09:28:59 +00:00
|
|
|
class MCValue;
|
|
|
|
|
|
|
|
/// MCObjectWriter - Defines the object file and target independent interfaces
|
|
|
|
/// used by the assembler backend to write native file format object files.
|
|
|
|
///
|
|
|
|
/// The object writer contains a few callbacks used by the assembler to allow
|
|
|
|
/// the object writer to modify the assembler data structures at appropriate
|
|
|
|
/// points. Once assembly is complete, the object writer is given the
|
|
|
|
/// MCAssembler instance, which contains all the symbol and section data which
|
|
|
|
/// should be emitted as part of WriteObject().
|
|
|
|
///
|
|
|
|
/// The object writer also contains a number of helper methods for writing
|
|
|
|
/// binary data to the output stream.
|
|
|
|
class MCObjectWriter {
|
2012-08-29 06:28:46 +00:00
|
|
|
MCObjectWriter(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
|
|
|
|
void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
|
2010-03-19 09:28:59 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
raw_ostream &OS;
|
|
|
|
|
|
|
|
unsigned IsLittleEndian : 1;
|
|
|
|
|
|
|
|
protected: // Can only create subclasses.
|
|
|
|
MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
|
|
|
|
: OS(_OS), IsLittleEndian(_IsLittleEndian) {}
|
|
|
|
|
|
|
|
public:
|
|
|
|
virtual ~MCObjectWriter();
|
|
|
|
|
2012-12-14 18:52:11 +00:00
|
|
|
/// lifetime management
|
|
|
|
virtual void reset() { }
|
|
|
|
|
2010-04-19 15:39:27 +00:00
|
|
|
bool isLittleEndian() const { return IsLittleEndian; }
|
2010-03-19 09:28:59 +00:00
|
|
|
|
|
|
|
raw_ostream &getStream() { return OS; }
|
|
|
|
|
|
|
|
/// @name High-Level API
|
|
|
|
/// @{
|
|
|
|
|
2013-02-05 17:10:07 +00:00
|
|
|
/// \brief Perform any late binding of symbols (for example, to assign symbol
|
|
|
|
/// indices for use when generating relocations).
|
2010-03-19 09:28:59 +00:00
|
|
|
///
|
|
|
|
/// This routine is called by the assembler after layout and relaxation is
|
|
|
|
/// complete.
|
2010-12-07 00:27:36 +00:00
|
|
|
virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
|
|
|
|
const MCAsmLayout &Layout) = 0;
|
2010-03-19 09:28:59 +00:00
|
|
|
|
2013-02-05 17:10:07 +00:00
|
|
|
/// \brief Record a relocation entry.
|
2010-03-19 09:28:59 +00:00
|
|
|
///
|
|
|
|
/// This routine is called by the assembler after layout and relaxation, and
|
|
|
|
/// post layout binding. The implementation is responsible for storing
|
|
|
|
/// information about the relocation so that it can be emitted during
|
|
|
|
/// WriteObject().
|
|
|
|
virtual void RecordRelocation(const MCAssembler &Asm,
|
2010-03-24 03:43:40 +00:00
|
|
|
const MCAsmLayout &Layout,
|
2010-03-22 20:35:50 +00:00
|
|
|
const MCFragment *Fragment,
|
2010-05-26 15:18:56 +00:00
|
|
|
const MCFixup &Fixup, MCValue Target,
|
2010-03-19 09:28:59 +00:00
|
|
|
uint64_t &FixedValue) = 0;
|
|
|
|
|
2010-12-17 04:54:54 +00:00
|
|
|
/// \brief Check whether the difference (A - B) between two symbol
|
|
|
|
/// references is fully resolved.
|
|
|
|
///
|
|
|
|
/// Clients are not required to answer precisely and may conservatively return
|
|
|
|
/// false, even when a difference is fully resolved.
|
2010-12-24 21:22:02 +00:00
|
|
|
bool
|
2010-12-17 04:54:54 +00:00
|
|
|
IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
|
|
|
|
const MCSymbolRefExpr *A,
|
2010-12-18 06:27:54 +00:00
|
|
|
const MCSymbolRefExpr *B,
|
|
|
|
bool InSet) const;
|
2010-12-17 04:54:54 +00:00
|
|
|
|
2010-12-24 21:22:02 +00:00
|
|
|
virtual bool
|
|
|
|
IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
|
|
|
const MCSymbolData &DataA,
|
|
|
|
const MCFragment &FB,
|
|
|
|
bool InSet,
|
2011-02-16 03:25:55 +00:00
|
|
|
bool IsPCRel) const;
|
2010-12-24 21:22:02 +00:00
|
|
|
|
2013-02-05 17:10:07 +00:00
|
|
|
/// \brief Write the object file.
|
2010-03-19 09:28:59 +00:00
|
|
|
///
|
|
|
|
/// This routine is called by the assembler after layout and relaxation is
|
2010-05-14 01:02:48 +00:00
|
|
|
/// complete, fixups have been evaluated and applied, and relocations
|
2010-03-19 09:28:59 +00:00
|
|
|
/// generated.
|
2010-10-05 15:11:03 +00:00
|
|
|
virtual void WriteObject(MCAssembler &Asm,
|
2010-03-24 03:43:40 +00:00
|
|
|
const MCAsmLayout &Layout) = 0;
|
2010-03-19 09:28:59 +00:00
|
|
|
|
|
|
|
/// @}
|
|
|
|
/// @name Binary Output
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
void Write8(uint8_t Value) {
|
|
|
|
OS << char(Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteLE16(uint16_t Value) {
|
2010-08-17 15:50:23 +00:00
|
|
|
Write8(uint8_t(Value >> 0));
|
|
|
|
Write8(uint8_t(Value >> 8));
|
2010-03-19 09:28:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WriteLE32(uint32_t Value) {
|
2010-08-17 15:50:23 +00:00
|
|
|
WriteLE16(uint16_t(Value >> 0));
|
|
|
|
WriteLE16(uint16_t(Value >> 16));
|
2010-03-19 09:28:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WriteLE64(uint64_t Value) {
|
2010-08-17 15:50:23 +00:00
|
|
|
WriteLE32(uint32_t(Value >> 0));
|
|
|
|
WriteLE32(uint32_t(Value >> 32));
|
2010-03-19 09:28:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WriteBE16(uint16_t Value) {
|
2010-08-17 15:50:23 +00:00
|
|
|
Write8(uint8_t(Value >> 8));
|
|
|
|
Write8(uint8_t(Value >> 0));
|
2010-03-19 09:28:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WriteBE32(uint32_t Value) {
|
2010-08-17 15:50:23 +00:00
|
|
|
WriteBE16(uint16_t(Value >> 16));
|
|
|
|
WriteBE16(uint16_t(Value >> 0));
|
2010-03-19 09:28:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WriteBE64(uint64_t Value) {
|
2010-08-17 15:50:23 +00:00
|
|
|
WriteBE32(uint32_t(Value >> 32));
|
|
|
|
WriteBE32(uint32_t(Value >> 0));
|
2010-03-19 09:28:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Write16(uint16_t Value) {
|
2010-08-17 15:50:23 +00:00
|
|
|
if (IsLittleEndian)
|
|
|
|
WriteLE16(Value);
|
|
|
|
else
|
|
|
|
WriteBE16(Value);
|
2010-03-19 09:28:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Write32(uint32_t Value) {
|
2010-08-17 15:50:23 +00:00
|
|
|
if (IsLittleEndian)
|
|
|
|
WriteLE32(Value);
|
|
|
|
else
|
|
|
|
WriteBE32(Value);
|
2010-03-19 09:28:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Write64(uint64_t Value) {
|
2010-08-17 15:50:23 +00:00
|
|
|
if (IsLittleEndian)
|
|
|
|
WriteLE64(Value);
|
|
|
|
else
|
|
|
|
WriteBE64(Value);
|
2010-03-19 09:28:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WriteZeros(unsigned N) {
|
|
|
|
const char Zeros[16] = { 0 };
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = N / 16; i != e; ++i)
|
|
|
|
OS << StringRef(Zeros, 16);
|
|
|
|
|
|
|
|
OS << StringRef(Zeros, N % 16);
|
|
|
|
}
|
|
|
|
|
2013-02-11 01:16:51 +00:00
|
|
|
void WriteBytes(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) {
|
2012-12-07 22:06:56 +00:00
|
|
|
WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
|
|
|
|
}
|
|
|
|
|
2010-03-19 09:28:59 +00:00
|
|
|
void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
|
2012-12-07 22:06:56 +00:00
|
|
|
// TODO: this version may need to go away once all fragment contents are
|
|
|
|
// converted to SmallVector<char, N>
|
2010-05-21 18:23:56 +00:00
|
|
|
assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
|
|
|
|
"data size greater than fill size, unexpected large write will occur");
|
2010-03-19 09:28:59 +00:00
|
|
|
OS << Str;
|
|
|
|
if (ZeroFillSize)
|
|
|
|
WriteZeros(ZeroFillSize - Str.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @}
|
2010-09-30 17:16:09 +00:00
|
|
|
|
2010-03-19 09:28:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // End llvm namespace
|
|
|
|
|
|
|
|
#endif
|