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