Line data Source code
1 : //===- MCLinkerOptimizationHint.h - LOH interface ---------------*- C++ -*-===//
2 : //
3 : //
4 : // The LLVM Compiler Infrastructure
5 : //
6 : // This file is distributed under the University of Illinois Open Source
7 : // License. See LICENSE.TXT for details.
8 : //
9 : //===----------------------------------------------------------------------===//
10 : //
11 : // This file declares some helpers classes to handle Linker Optimization Hint
12 : // (LOH).
13 : //
14 : // FIXME: LOH interface supports only MachO format at the moment.
15 : //===----------------------------------------------------------------------===//
16 :
17 : #ifndef LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
18 : #define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
19 :
20 : #include "llvm/ADT/SmallVector.h"
21 : #include "llvm/ADT/StringRef.h"
22 : #include "llvm/ADT/StringSwitch.h"
23 : #include "llvm/Support/raw_ostream.h"
24 : #include <cassert>
25 : #include <cstdint>
26 :
27 : namespace llvm {
28 :
29 : class MachObjectWriter;
30 : class MCAsmLayout;
31 : class MCSymbol;
32 :
33 : /// Linker Optimization Hint Type.
34 : enum MCLOHType {
35 : MCLOH_AdrpAdrp = 0x1u, ///< Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE.
36 : MCLOH_AdrpLdr = 0x2u, ///< Adrp _v@PAGE -> Ldr _v@PAGEOFF.
37 : MCLOH_AdrpAddLdr = 0x3u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr.
38 : MCLOH_AdrpLdrGotLdr = 0x4u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr.
39 : MCLOH_AdrpAddStr = 0x5u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Str.
40 : MCLOH_AdrpLdrGotStr = 0x6u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str.
41 : MCLOH_AdrpAdd = 0x7u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF.
42 : MCLOH_AdrpLdrGot = 0x8u ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF.
43 : };
44 :
45 : static inline StringRef MCLOHDirectiveName() {
46 : return StringRef(".loh");
47 : }
48 :
49 : static inline bool isValidMCLOHType(unsigned Kind) {
50 0 : return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot;
51 : }
52 :
53 12 : static inline int MCLOHNameToId(StringRef Name) {
54 : #define MCLOHCaseNameToId(Name) .Case(#Name, MCLOH_ ## Name)
55 12 : return StringSwitch<int>(Name)
56 12 : MCLOHCaseNameToId(AdrpAdrp)
57 12 : MCLOHCaseNameToId(AdrpLdr)
58 12 : MCLOHCaseNameToId(AdrpAddLdr)
59 12 : MCLOHCaseNameToId(AdrpLdrGotLdr)
60 12 : MCLOHCaseNameToId(AdrpAddStr)
61 12 : MCLOHCaseNameToId(AdrpLdrGotStr)
62 12 : MCLOHCaseNameToId(AdrpAdd)
63 12 : MCLOHCaseNameToId(AdrpLdrGot)
64 12 : .Default(-1);
65 : }
66 :
67 237 : static inline StringRef MCLOHIdToName(MCLOHType Kind) {
68 : #define MCLOHCaseIdToName(Name) case MCLOH_ ## Name: return StringRef(#Name);
69 237 : switch (Kind) {
70 13 : MCLOHCaseIdToName(AdrpAdrp);
71 64 : MCLOHCaseIdToName(AdrpLdr);
72 4 : MCLOHCaseIdToName(AdrpAddLdr);
73 40 : MCLOHCaseIdToName(AdrpLdrGotLdr);
74 3 : MCLOHCaseIdToName(AdrpAddStr);
75 16 : MCLOHCaseIdToName(AdrpLdrGotStr);
76 24 : MCLOHCaseIdToName(AdrpAdd);
77 73 : MCLOHCaseIdToName(AdrpLdrGot);
78 : }
79 0 : return StringRef();
80 : }
81 :
82 : static inline int MCLOHIdToNbArgs(MCLOHType Kind) {
83 : switch (Kind) {
84 : // LOH with two arguments
85 : case MCLOH_AdrpAdrp:
86 : case MCLOH_AdrpLdr:
87 : case MCLOH_AdrpAdd:
88 : case MCLOH_AdrpLdrGot:
89 : return 2;
90 : // LOH with three arguments
91 : case MCLOH_AdrpAddLdr:
92 : case MCLOH_AdrpLdrGotLdr:
93 : case MCLOH_AdrpAddStr:
94 : case MCLOH_AdrpLdrGotStr:
95 : return 3;
96 : }
97 : return -1;
98 : }
99 :
100 : /// Store Linker Optimization Hint information (LOH).
101 2 : class MCLOHDirective {
102 : MCLOHType Kind;
103 :
104 : /// Arguments of this directive. Order matters.
105 : SmallVector<MCSymbol *, 3> Args;
106 :
107 : /// Emit this directive in \p OutStream using the information available
108 : /// in the given \p ObjWriter and \p Layout to get the address of the
109 : /// arguments within the object file.
110 : void emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter,
111 : const MCAsmLayout &Layout) const;
112 :
113 : public:
114 : using LOHArgs = SmallVectorImpl<MCSymbol *>;
115 :
116 : MCLOHDirective(MCLOHType Kind, const LOHArgs &Args)
117 1 : : Kind(Kind), Args(Args.begin(), Args.end()) {
118 : assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!");
119 : }
120 :
121 : MCLOHType getKind() const { return Kind; }
122 :
123 : const LOHArgs &getArgs() const { return Args; }
124 :
125 : /// Emit this directive as:
126 : /// <kind, numArgs, addr1, ..., addrN>
127 : void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const;
128 :
129 : /// Get the size in bytes of this directive if emitted in \p ObjWriter with
130 : /// the given \p Layout.
131 : uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
132 : const MCAsmLayout &Layout) const;
133 : };
134 :
135 35343 : class MCLOHContainer {
136 : /// Keep track of the emit size of all the LOHs.
137 : mutable uint64_t EmitSize = 0;
138 :
139 : /// Keep track of all LOH directives.
140 : SmallVector<MCLOHDirective, 32> Directives;
141 :
142 : public:
143 : using LOHDirectives = SmallVectorImpl<MCLOHDirective>;
144 :
145 35527 : MCLOHContainer() = default;
146 :
147 : /// Const accessor to the directives.
148 : const LOHDirectives &getDirectives() const {
149 : return Directives;
150 : }
151 :
152 : /// Add the directive of the given kind \p Kind with the given arguments
153 : /// \p Args to the container.
154 1 : void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) {
155 1 : Directives.push_back(MCLOHDirective(Kind, Args));
156 1 : }
157 :
158 : /// Get the size of the directives if emitted.
159 612 : uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
160 : const MCAsmLayout &Layout) const {
161 612 : if (!EmitSize) {
162 613 : for (const MCLOHDirective &D : Directives)
163 1 : EmitSize += D.getEmitSize(ObjWriter, Layout);
164 : }
165 612 : return EmitSize;
166 : }
167 :
168 : /// Emit all Linker Optimization Hint in one big table.
169 : /// Each line of the table is emitted by LOHDirective::emit.
170 : void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
171 2 : for (const MCLOHDirective &D : Directives)
172 1 : D.emit(ObjWriter, Layout);
173 : }
174 :
175 : void reset() {
176 16280 : Directives.clear();
177 8140 : EmitSize = 0;
178 : }
179 : };
180 :
181 : // Add types for specialized template using MCSymbol.
182 : using MCLOHArgs = MCLOHDirective::LOHArgs;
183 : using MCLOHDirectives = MCLOHContainer::LOHDirectives;
184 :
185 : } // end namespace llvm
186 :
187 : #endif // LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
|