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 MCAssembler;
19 class MCFixup;
20 class MCFragment;
21 class MCSymbol;
22 class MCSymbolRefExpr;
23 class MCValue;
24 
25 /// Defines the object file and target independent interfaces used by the
26 /// assembler backend to write native file format object files.
27 ///
28 /// The object writer contains a few callbacks used by the assembler to allow
29 /// the object writer to modify the assembler data structures at appropriate
30 /// points. Once assembly is complete, the object writer is given the
31 /// MCAssembler instance, which contains all the symbol and section data which
32 /// should be emitted as part of writeObject().
33 class MCObjectWriter {
34 protected:
35   /// List of declared file names
36   SmallVector<std::pair<std::string, size_t>, 0> FileNames;
37   // XCOFF specific: Optional compiler version.
38   std::string CompilerVersion;
39   std::vector<const MCSymbol *> AddrsigSyms;
40   bool EmitAddrsigSection = false;
41   bool SubsectionsViaSymbols = false;
42 
43   struct CGProfileEntry {
44     const MCSymbolRefExpr *From;
45     const MCSymbolRefExpr *To;
46     uint64_t Count;
47   };
48   SmallVector<CGProfileEntry, 0> CGProfile;
49 
50   MCObjectWriter() = default;
51 
52 public:
53   MCObjectWriter(const MCObjectWriter &) = delete;
54   MCObjectWriter &operator=(const MCObjectWriter &) = delete;
55   virtual ~MCObjectWriter();
56 
57   /// lifetime management
58   virtual void reset();
59 
60   /// \name High-Level API
61   /// @{
62 
63   /// Perform any late binding of symbols (for example, to assign symbol
64   /// indices for use when generating relocations).
65   ///
66   /// This routine is called by the assembler after layout and relaxation is
67   /// complete.
executePostLayoutBinding(MCAssembler & Asm)68   virtual void executePostLayoutBinding(MCAssembler &Asm) {}
69 
70   /// Record a relocation entry.
71   ///
72   /// This routine is called by the assembler after layout and relaxation, and
73   /// post layout binding. The implementation is responsible for storing
74   /// information about the relocation so that it can be emitted during
75   /// writeObject().
76   virtual void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment,
77                                 const MCFixup &Fixup, MCValue Target,
78                                 uint64_t &FixedValue) = 0;
79 
80   /// Check whether the difference (A - B) between two symbol references is
81   /// fully resolved.
82   ///
83   /// Clients are not required to answer precisely and may conservatively return
84   /// false, even when a difference is fully resolved.
85   bool isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
86                                           const MCSymbolRefExpr *A,
87                                           const MCSymbolRefExpr *B,
88                                           bool InSet) const;
89 
90   virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
91                                                       const MCSymbol &SymA,
92                                                       const MCFragment &FB,
93                                                       bool InSet,
94                                                       bool IsPCRel) const;
95 
getFileNames()96   MutableArrayRef<std::pair<std::string, size_t>> getFileNames() {
97     return FileNames;
98   }
99   void addFileName(MCAssembler &Asm, StringRef FileName);
setCompilerVersion(StringRef CompilerVers)100   void setCompilerVersion(StringRef CompilerVers) {
101     CompilerVersion = CompilerVers;
102   }
103 
104   /// Tell the object writer to emit an address-significance table during
105   /// writeObject(). If this function is not called, all symbols are treated as
106   /// address-significant.
emitAddrsigSection()107   void emitAddrsigSection() { EmitAddrsigSection = true; }
108 
getEmitAddrsigSection()109   bool getEmitAddrsigSection() { return EmitAddrsigSection; }
110 
111   /// Record the given symbol in the address-significance table to be written
112   /// diring writeObject().
addAddrsigSymbol(const MCSymbol * Sym)113   void addAddrsigSymbol(const MCSymbol *Sym) { AddrsigSyms.push_back(Sym); }
114 
getAddrsigSyms()115   std::vector<const MCSymbol *> &getAddrsigSyms() { return AddrsigSyms; }
getCGProfile()116   SmallVector<CGProfileEntry, 0> &getCGProfile() { return CGProfile; }
117 
118   // Mach-O specific: Whether .subsections_via_symbols is enabled.
getSubsectionsViaSymbols()119   bool getSubsectionsViaSymbols() const { return SubsectionsViaSymbols; }
setSubsectionsViaSymbols(bool Value)120   void setSubsectionsViaSymbols(bool Value) { SubsectionsViaSymbols = Value; }
121 
122   /// Write the object file and returns the number of bytes written.
123   ///
124   /// This routine is called by the assembler after layout and relaxation is
125   /// complete, fixups have been evaluated and applied, and relocations
126   /// generated.
127   virtual uint64_t writeObject(MCAssembler &Asm) = 0;
128 
129   /// @}
130 };
131 
132 /// Base class for classes that define behaviour that is specific to both the
133 /// target and the object format.
134 class MCObjectTargetWriter {
135 public:
136   virtual ~MCObjectTargetWriter() = default;
137   virtual Triple::ObjectFormatType getFormat() const = 0;
138 };
139 
140 } // end namespace llvm
141 
142 #endif // LLVM_MC_MCOBJECTWRITER_H
143