1 //===- llvm/MC/MCObjectWriter.h - Object File Writer Interface --*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_MC_MCOBJECTWRITER_H
10 #define LLVM_MC_MCOBJECTWRITER_H
11 
12 #include "llvm/MC/MCSymbol.h"
13 #include "llvm/TargetParser/Triple.h"
14 #include <cstdint>
15 
16 namespace llvm {
17 
18 class MCAsmLayout;
19 class MCAssembler;
20 class MCFixup;
21 class MCFragment;
22 class MCSymbol;
23 class MCSymbolRefExpr;
24 class MCValue;
25 
26 /// Defines the object file and target independent interfaces used by the
27 /// assembler backend to write native file format object files.
28 ///
29 /// The object writer contains a few callbacks used by the assembler to allow
30 /// the object writer to modify the assembler data structures at appropriate
31 /// points. Once assembly is complete, the object writer is given the
32 /// MCAssembler instance, which contains all the symbol and section data which
33 /// should be emitted as part of writeObject().
34 class MCObjectWriter {
35 protected:
36   std::vector<const MCSymbol *> AddrsigSyms;
37   bool EmitAddrsigSection = false;
38 
39   MCObjectWriter() = default;
40 
41 public:
42   MCObjectWriter(const MCObjectWriter &) = delete;
43   MCObjectWriter &operator=(const MCObjectWriter &) = delete;
44   virtual ~MCObjectWriter();
45 
46   /// lifetime management
47   virtual void reset() {}
48 
49   /// \name High-Level API
50   /// @{
51 
52   /// Perform any late binding of symbols (for example, to assign symbol
53   /// indices for use when generating relocations).
54   ///
55   /// This routine is called by the assembler after layout and relaxation is
56   /// complete.
57   virtual void executePostLayoutBinding(MCAssembler &Asm,
58                                         const MCAsmLayout &Layout) = 0;
59 
60   /// Record a relocation entry.
61   ///
62   /// This routine is called by the assembler after layout and relaxation, and
63   /// post layout binding. The implementation is responsible for storing
64   /// information about the relocation so that it can be emitted during
65   /// writeObject().
66   virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
67                                 const MCFragment *Fragment,
68                                 const MCFixup &Fixup, MCValue Target,
69                                 uint64_t &FixedValue) = 0;
70 
71   /// Check whether the difference (A - B) between two symbol references is
72   /// fully resolved.
73   ///
74   /// Clients are not required to answer precisely and may conservatively return
75   /// false, even when a difference is fully resolved.
76   bool isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
77                                           const MCSymbolRefExpr *A,
78                                           const MCSymbolRefExpr *B,
79                                           bool InSet) const;
80 
81   virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
82                                                       const MCSymbol &A,
83                                                       const MCSymbol &B,
84                                                       bool InSet) const;
85 
86   virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
87                                                       const MCSymbol &SymA,
88                                                       const MCFragment &FB,
89                                                       bool InSet,
90                                                       bool IsPCRel) const;
91 
92   /// ELF only. Mark that we have seen GNU ABI usage (e.g. SHF_GNU_RETAIN).
93   virtual void markGnuAbi() {}
94 
95   /// ELF only, override the default ABIVersion in the ELF header.
96   virtual void setOverrideABIVersion(uint8_t ABIVersion) {}
97 
98   /// Tell the object writer to emit an address-significance table during
99   /// writeObject(). If this function is not called, all symbols are treated as
100   /// address-significant.
101   void emitAddrsigSection() { EmitAddrsigSection = true; }
102 
103   bool getEmitAddrsigSection() { return EmitAddrsigSection; }
104 
105   /// Record the given symbol in the address-significance table to be written
106   /// diring writeObject().
107   void addAddrsigSymbol(const MCSymbol *Sym) { AddrsigSyms.push_back(Sym); }
108 
109   std::vector<const MCSymbol *> &getAddrsigSyms() { return AddrsigSyms; }
110 
111   virtual void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap,
112                                  unsigned LanguageCode, unsigned ReasonCode,
113                                  unsigned FunctionSize, bool hasDebug) {
114     report_fatal_error("addExceptionEntry is only supported on XCOFF targets");
115   }
116   virtual void addCInfoSymEntry(StringRef Name, StringRef Metadata) {
117     report_fatal_error("addCInfoSymEntry is only supported on XCOFF targets");
118   }
119   /// Write the object file and returns the number of bytes written.
120   ///
121   /// This routine is called by the assembler after layout and relaxation is
122   /// complete, fixups have been evaluated and applied, and relocations
123   /// generated.
124   virtual uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0;
125 
126   /// @}
127 };
128 
129 /// Base class for classes that define behaviour that is specific to both the
130 /// target and the object format.
131 class MCObjectTargetWriter {
132 public:
133   virtual ~MCObjectTargetWriter() = default;
134   virtual Triple::ObjectFormatType getFormat() const = 0;
135 };
136 
137 } // end namespace llvm
138 
139 #endif // LLVM_MC_MCOBJECTWRITER_H
140