xref: /aosp_15_r20/external/llvm/include/llvm/MC/MCObjectWriter.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_MC_MCOBJECTWRITER_H
11*9880d681SAndroid Build Coastguard Worker #define LLVM_MC_MCOBJECTWRITER_H
12*9880d681SAndroid Build Coastguard Worker 
13*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Compiler.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/DataTypes.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/EndianStream.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
18*9880d681SAndroid Build Coastguard Worker #include <cassert>
19*9880d681SAndroid Build Coastguard Worker 
20*9880d681SAndroid Build Coastguard Worker namespace llvm {
21*9880d681SAndroid Build Coastguard Worker class MCAsmLayout;
22*9880d681SAndroid Build Coastguard Worker class MCAssembler;
23*9880d681SAndroid Build Coastguard Worker class MCFixup;
24*9880d681SAndroid Build Coastguard Worker class MCFragment;
25*9880d681SAndroid Build Coastguard Worker class MCSymbol;
26*9880d681SAndroid Build Coastguard Worker class MCSymbolRefExpr;
27*9880d681SAndroid Build Coastguard Worker class MCValue;
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker /// Defines the object file and target independent interfaces used by the
30*9880d681SAndroid Build Coastguard Worker /// assembler backend to write native file format object files.
31*9880d681SAndroid Build Coastguard Worker ///
32*9880d681SAndroid Build Coastguard Worker /// The object writer contains a few callbacks used by the assembler to allow
33*9880d681SAndroid Build Coastguard Worker /// the object writer to modify the assembler data structures at appropriate
34*9880d681SAndroid Build Coastguard Worker /// points. Once assembly is complete, the object writer is given the
35*9880d681SAndroid Build Coastguard Worker /// MCAssembler instance, which contains all the symbol and section data which
36*9880d681SAndroid Build Coastguard Worker /// should be emitted as part of writeObject().
37*9880d681SAndroid Build Coastguard Worker ///
38*9880d681SAndroid Build Coastguard Worker /// The object writer also contains a number of helper methods for writing
39*9880d681SAndroid Build Coastguard Worker /// binary data to the output stream.
40*9880d681SAndroid Build Coastguard Worker class MCObjectWriter {
41*9880d681SAndroid Build Coastguard Worker   MCObjectWriter(const MCObjectWriter &) = delete;
42*9880d681SAndroid Build Coastguard Worker   void operator=(const MCObjectWriter &) = delete;
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker   raw_pwrite_stream *OS;
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker protected:
47*9880d681SAndroid Build Coastguard Worker   unsigned IsLittleEndian : 1;
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker protected: // Can only create subclasses.
MCObjectWriter(raw_pwrite_stream & OS,bool IsLittleEndian)50*9880d681SAndroid Build Coastguard Worker   MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian)
51*9880d681SAndroid Build Coastguard Worker       : OS(&OS), IsLittleEndian(IsLittleEndian) {}
52*9880d681SAndroid Build Coastguard Worker 
getInitialOffset()53*9880d681SAndroid Build Coastguard Worker   unsigned getInitialOffset() {
54*9880d681SAndroid Build Coastguard Worker     return OS->tell();
55*9880d681SAndroid Build Coastguard Worker   }
56*9880d681SAndroid Build Coastguard Worker 
57*9880d681SAndroid Build Coastguard Worker public:
58*9880d681SAndroid Build Coastguard Worker   virtual ~MCObjectWriter();
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker   /// lifetime management
reset()61*9880d681SAndroid Build Coastguard Worker   virtual void reset() {}
62*9880d681SAndroid Build Coastguard Worker 
isLittleEndian()63*9880d681SAndroid Build Coastguard Worker   bool isLittleEndian() const { return IsLittleEndian; }
64*9880d681SAndroid Build Coastguard Worker 
getStream()65*9880d681SAndroid Build Coastguard Worker   raw_pwrite_stream &getStream() { return *OS; }
setStream(raw_pwrite_stream & NewOS)66*9880d681SAndroid Build Coastguard Worker   void setStream(raw_pwrite_stream &NewOS) { OS = &NewOS; }
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker   /// \name High-Level API
69*9880d681SAndroid Build Coastguard Worker   /// @{
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker   /// Perform any late binding of symbols (for example, to assign symbol
72*9880d681SAndroid Build Coastguard Worker   /// indices for use when generating relocations).
73*9880d681SAndroid Build Coastguard Worker   ///
74*9880d681SAndroid Build Coastguard Worker   /// This routine is called by the assembler after layout and relaxation is
75*9880d681SAndroid Build Coastguard Worker   /// complete.
76*9880d681SAndroid Build Coastguard Worker   virtual void executePostLayoutBinding(MCAssembler &Asm,
77*9880d681SAndroid Build Coastguard Worker                                         const MCAsmLayout &Layout) = 0;
78*9880d681SAndroid Build Coastguard Worker 
79*9880d681SAndroid Build Coastguard Worker   /// Record a relocation entry.
80*9880d681SAndroid Build Coastguard Worker   ///
81*9880d681SAndroid Build Coastguard Worker   /// This routine is called by the assembler after layout and relaxation, and
82*9880d681SAndroid Build Coastguard Worker   /// post layout binding. The implementation is responsible for storing
83*9880d681SAndroid Build Coastguard Worker   /// information about the relocation so that it can be emitted during
84*9880d681SAndroid Build Coastguard Worker   /// writeObject().
85*9880d681SAndroid Build Coastguard Worker   virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
86*9880d681SAndroid Build Coastguard Worker                                 const MCFragment *Fragment,
87*9880d681SAndroid Build Coastguard Worker                                 const MCFixup &Fixup, MCValue Target,
88*9880d681SAndroid Build Coastguard Worker                                 bool &IsPCRel, uint64_t &FixedValue) = 0;
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker   /// Check whether the difference (A - B) between two symbol references is
91*9880d681SAndroid Build Coastguard Worker   /// fully resolved.
92*9880d681SAndroid Build Coastguard Worker   ///
93*9880d681SAndroid Build Coastguard Worker   /// Clients are not required to answer precisely and may conservatively return
94*9880d681SAndroid Build Coastguard Worker   /// false, even when a difference is fully resolved.
95*9880d681SAndroid Build Coastguard Worker   bool isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
96*9880d681SAndroid Build Coastguard Worker                                           const MCSymbolRefExpr *A,
97*9880d681SAndroid Build Coastguard Worker                                           const MCSymbolRefExpr *B,
98*9880d681SAndroid Build Coastguard Worker                                           bool InSet) const;
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker   virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
101*9880d681SAndroid Build Coastguard Worker                                                       const MCSymbol &A,
102*9880d681SAndroid Build Coastguard Worker                                                       const MCSymbol &B,
103*9880d681SAndroid Build Coastguard Worker                                                       bool InSet) const;
104*9880d681SAndroid Build Coastguard Worker 
105*9880d681SAndroid Build Coastguard Worker   virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
106*9880d681SAndroid Build Coastguard Worker                                                       const MCSymbol &SymA,
107*9880d681SAndroid Build Coastguard Worker                                                       const MCFragment &FB,
108*9880d681SAndroid Build Coastguard Worker                                                       bool InSet,
109*9880d681SAndroid Build Coastguard Worker                                                       bool IsPCRel) const;
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker   /// True if this symbol (which is a variable) is weak. This is not
112*9880d681SAndroid Build Coastguard Worker   /// just STB_WEAK, but more generally whether or not we can evaluate
113*9880d681SAndroid Build Coastguard Worker   /// past it.
114*9880d681SAndroid Build Coastguard Worker   virtual bool isWeak(const MCSymbol &Sym) const;
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker   /// Write the object file.
117*9880d681SAndroid Build Coastguard Worker   ///
118*9880d681SAndroid Build Coastguard Worker   /// This routine is called by the assembler after layout and relaxation is
119*9880d681SAndroid Build Coastguard Worker   /// complete, fixups have been evaluated and applied, and relocations
120*9880d681SAndroid Build Coastguard Worker   /// generated.
121*9880d681SAndroid Build Coastguard Worker   virtual void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0;
122*9880d681SAndroid Build Coastguard Worker 
123*9880d681SAndroid Build Coastguard Worker   /// @}
124*9880d681SAndroid Build Coastguard Worker   /// \name Binary Output
125*9880d681SAndroid Build Coastguard Worker   /// @{
126*9880d681SAndroid Build Coastguard Worker 
write8(uint8_t Value)127*9880d681SAndroid Build Coastguard Worker   void write8(uint8_t Value) { *OS << char(Value); }
128*9880d681SAndroid Build Coastguard Worker 
writeLE16(uint16_t Value)129*9880d681SAndroid Build Coastguard Worker   void writeLE16(uint16_t Value) {
130*9880d681SAndroid Build Coastguard Worker     support::endian::Writer<support::little>(*OS).write(Value);
131*9880d681SAndroid Build Coastguard Worker   }
132*9880d681SAndroid Build Coastguard Worker 
writeLE32(uint32_t Value)133*9880d681SAndroid Build Coastguard Worker   void writeLE32(uint32_t Value) {
134*9880d681SAndroid Build Coastguard Worker     support::endian::Writer<support::little>(*OS).write(Value);
135*9880d681SAndroid Build Coastguard Worker   }
136*9880d681SAndroid Build Coastguard Worker 
writeLE64(uint64_t Value)137*9880d681SAndroid Build Coastguard Worker   void writeLE64(uint64_t Value) {
138*9880d681SAndroid Build Coastguard Worker     support::endian::Writer<support::little>(*OS).write(Value);
139*9880d681SAndroid Build Coastguard Worker   }
140*9880d681SAndroid Build Coastguard Worker 
writeBE16(uint16_t Value)141*9880d681SAndroid Build Coastguard Worker   void writeBE16(uint16_t Value) {
142*9880d681SAndroid Build Coastguard Worker     support::endian::Writer<support::big>(*OS).write(Value);
143*9880d681SAndroid Build Coastguard Worker   }
144*9880d681SAndroid Build Coastguard Worker 
writeBE32(uint32_t Value)145*9880d681SAndroid Build Coastguard Worker   void writeBE32(uint32_t Value) {
146*9880d681SAndroid Build Coastguard Worker     support::endian::Writer<support::big>(*OS).write(Value);
147*9880d681SAndroid Build Coastguard Worker   }
148*9880d681SAndroid Build Coastguard Worker 
writeBE64(uint64_t Value)149*9880d681SAndroid Build Coastguard Worker   void writeBE64(uint64_t Value) {
150*9880d681SAndroid Build Coastguard Worker     support::endian::Writer<support::big>(*OS).write(Value);
151*9880d681SAndroid Build Coastguard Worker   }
152*9880d681SAndroid Build Coastguard Worker 
write16(uint16_t Value)153*9880d681SAndroid Build Coastguard Worker   void write16(uint16_t Value) {
154*9880d681SAndroid Build Coastguard Worker     if (IsLittleEndian)
155*9880d681SAndroid Build Coastguard Worker       writeLE16(Value);
156*9880d681SAndroid Build Coastguard Worker     else
157*9880d681SAndroid Build Coastguard Worker       writeBE16(Value);
158*9880d681SAndroid Build Coastguard Worker   }
159*9880d681SAndroid Build Coastguard Worker 
write32(uint32_t Value)160*9880d681SAndroid Build Coastguard Worker   void write32(uint32_t Value) {
161*9880d681SAndroid Build Coastguard Worker     if (IsLittleEndian)
162*9880d681SAndroid Build Coastguard Worker       writeLE32(Value);
163*9880d681SAndroid Build Coastguard Worker     else
164*9880d681SAndroid Build Coastguard Worker       writeBE32(Value);
165*9880d681SAndroid Build Coastguard Worker   }
166*9880d681SAndroid Build Coastguard Worker 
write64(uint64_t Value)167*9880d681SAndroid Build Coastguard Worker   void write64(uint64_t Value) {
168*9880d681SAndroid Build Coastguard Worker     if (IsLittleEndian)
169*9880d681SAndroid Build Coastguard Worker       writeLE64(Value);
170*9880d681SAndroid Build Coastguard Worker     else
171*9880d681SAndroid Build Coastguard Worker       writeBE64(Value);
172*9880d681SAndroid Build Coastguard Worker   }
173*9880d681SAndroid Build Coastguard Worker 
WriteZeros(unsigned N)174*9880d681SAndroid Build Coastguard Worker   void WriteZeros(unsigned N) {
175*9880d681SAndroid Build Coastguard Worker     const char Zeros[16] = {0};
176*9880d681SAndroid Build Coastguard Worker 
177*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = N / 16; i != e; ++i)
178*9880d681SAndroid Build Coastguard Worker       *OS << StringRef(Zeros, 16);
179*9880d681SAndroid Build Coastguard Worker 
180*9880d681SAndroid Build Coastguard Worker     *OS << StringRef(Zeros, N % 16);
181*9880d681SAndroid Build Coastguard Worker   }
182*9880d681SAndroid Build Coastguard Worker 
183*9880d681SAndroid Build Coastguard Worker   void writeBytes(const SmallVectorImpl<char> &ByteVec,
184*9880d681SAndroid Build Coastguard Worker                   unsigned ZeroFillSize = 0) {
185*9880d681SAndroid Build Coastguard Worker     writeBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
186*9880d681SAndroid Build Coastguard Worker   }
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker   void writeBytes(StringRef Str, unsigned ZeroFillSize = 0) {
189*9880d681SAndroid Build Coastguard Worker     // TODO: this version may need to go away once all fragment contents are
190*9880d681SAndroid Build Coastguard Worker     // converted to SmallVector<char, N>
191*9880d681SAndroid Build Coastguard Worker     assert(
192*9880d681SAndroid Build Coastguard Worker         (ZeroFillSize == 0 || Str.size() <= ZeroFillSize) &&
193*9880d681SAndroid Build Coastguard Worker         "data size greater than fill size, unexpected large write will occur");
194*9880d681SAndroid Build Coastguard Worker     *OS << Str;
195*9880d681SAndroid Build Coastguard Worker     if (ZeroFillSize)
196*9880d681SAndroid Build Coastguard Worker       WriteZeros(ZeroFillSize - Str.size());
197*9880d681SAndroid Build Coastguard Worker   }
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker   /// @}
200*9880d681SAndroid Build Coastguard Worker };
201*9880d681SAndroid Build Coastguard Worker 
202*9880d681SAndroid Build Coastguard Worker } // End llvm namespace
203*9880d681SAndroid Build Coastguard Worker 
204*9880d681SAndroid Build Coastguard Worker #endif
205