mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-23 17:29:19 +00:00
actuall addresses in a .o file, so it is better to let the MachO writer compute it. This is good for two reasons. First, areas that shouldn't care about addresses now don't have access to it. Second, the layout of each section is independent. I should use this in a subsequent commit to speed it up. Most of the patch is just removing the section address computation. The two interesting parts are the change on how we handle padding in the end of sections and how MachO can get the address of a-b when a and b are in different sections. Since now the expression evaluation normally doesn't know the section address, it will think that a-b needs relocation and let the MachO writer know. Once it has computed the section addresses, it calls back the expression evaluation with the section addresses to resolve these expressions. The remaining problem is the handling of padding. Currently it will create a special alignment fragment at the end. Since that fragment doesn't update the alignment of the section, it needs the real address to be computed. Since now the layout will not compute a-b with a and b in different sections, the only effect that the special alignment fragment has is update the address size of the section. This can also be done by the MachO writer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121076 91177308-0d34-0410-b5e6-96231b3b80d8
194 lines
5.8 KiB
C++
194 lines
5.8 KiB
C++
//===-- 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
|
|
|
|
#include "llvm/ADT/Triple.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/Support/DataTypes.h"
|
|
#include <cassert>
|
|
|
|
namespace llvm {
|
|
class MCAsmLayout;
|
|
class MCAssembler;
|
|
class MCFixup;
|
|
class MCFragment;
|
|
class MCValue;
|
|
class raw_ostream;
|
|
|
|
/// 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 {
|
|
MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT
|
|
void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT
|
|
|
|
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();
|
|
|
|
bool isLittleEndian() const { return IsLittleEndian; }
|
|
|
|
raw_ostream &getStream() { return OS; }
|
|
|
|
/// @name High-Level API
|
|
/// @{
|
|
|
|
/// Perform any late binding of symbols (for example, to assign symbol indices
|
|
/// for use when generating relocations).
|
|
///
|
|
/// This routine is called by the assembler after layout and relaxation is
|
|
/// complete.
|
|
virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
|
|
const MCAsmLayout &Layout) = 0;
|
|
|
|
/// Record a relocation entry.
|
|
///
|
|
/// 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,
|
|
const MCAsmLayout &Layout,
|
|
const MCFragment *Fragment,
|
|
const MCFixup &Fixup, MCValue Target,
|
|
uint64_t &FixedValue) = 0;
|
|
|
|
/// Check if a fixup is fully resolved.
|
|
///
|
|
/// This routine is used by the assembler to let the file format decide
|
|
/// if a fixup is not fully resolved. For example, one that crosses
|
|
/// two sections on ELF.
|
|
virtual bool IsFixupFullyResolved(const MCAssembler &Asm,
|
|
const MCValue Target,
|
|
bool IsPCRel,
|
|
const MCFragment *DF) const = 0;
|
|
|
|
/// Write the object file.
|
|
///
|
|
/// This routine is called by the assembler after layout and relaxation is
|
|
/// complete, fixups have been evaluated and applied, and relocations
|
|
/// generated.
|
|
virtual void WriteObject(MCAssembler &Asm,
|
|
const MCAsmLayout &Layout) = 0;
|
|
|
|
/// @}
|
|
/// @name Binary Output
|
|
/// @{
|
|
|
|
void Write8(uint8_t Value) {
|
|
OS << char(Value);
|
|
}
|
|
|
|
void WriteLE16(uint16_t Value) {
|
|
Write8(uint8_t(Value >> 0));
|
|
Write8(uint8_t(Value >> 8));
|
|
}
|
|
|
|
void WriteLE32(uint32_t Value) {
|
|
WriteLE16(uint16_t(Value >> 0));
|
|
WriteLE16(uint16_t(Value >> 16));
|
|
}
|
|
|
|
void WriteLE64(uint64_t Value) {
|
|
WriteLE32(uint32_t(Value >> 0));
|
|
WriteLE32(uint32_t(Value >> 32));
|
|
}
|
|
|
|
void WriteBE16(uint16_t Value) {
|
|
Write8(uint8_t(Value >> 8));
|
|
Write8(uint8_t(Value >> 0));
|
|
}
|
|
|
|
void WriteBE32(uint32_t Value) {
|
|
WriteBE16(uint16_t(Value >> 16));
|
|
WriteBE16(uint16_t(Value >> 0));
|
|
}
|
|
|
|
void WriteBE64(uint64_t Value) {
|
|
WriteBE32(uint32_t(Value >> 32));
|
|
WriteBE32(uint32_t(Value >> 0));
|
|
}
|
|
|
|
void Write16(uint16_t Value) {
|
|
if (IsLittleEndian)
|
|
WriteLE16(Value);
|
|
else
|
|
WriteBE16(Value);
|
|
}
|
|
|
|
void Write32(uint32_t Value) {
|
|
if (IsLittleEndian)
|
|
WriteLE32(Value);
|
|
else
|
|
WriteBE32(Value);
|
|
}
|
|
|
|
void Write64(uint64_t Value) {
|
|
if (IsLittleEndian)
|
|
WriteLE64(Value);
|
|
else
|
|
WriteBE64(Value);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
|
|
assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
|
|
"data size greater than fill size, unexpected large write will occur");
|
|
OS << Str;
|
|
if (ZeroFillSize)
|
|
WriteZeros(ZeroFillSize - Str.size());
|
|
}
|
|
|
|
/// @}
|
|
|
|
/// Utility function to encode a SLEB128 value.
|
|
static void EncodeSLEB128(int64_t Value, raw_ostream &OS);
|
|
/// Utility function to encode a ULEB128 value.
|
|
static void EncodeULEB128(uint64_t Value, raw_ostream &OS);
|
|
};
|
|
|
|
MCObjectWriter *createMachObjectWriter(raw_ostream &OS, bool is64Bit,
|
|
uint32_t CPUType, uint32_t CPUSubtype,
|
|
bool IsLittleEndian);
|
|
MCObjectWriter *createELFObjectWriter(raw_ostream &OS, bool is64Bit,
|
|
Triple::OSType OSType, uint16_t EMachine,
|
|
bool IsLittleEndian,
|
|
bool HasRelocationAddend);
|
|
MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit);
|
|
|
|
} // End llvm namespace
|
|
|
|
#endif
|