/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/MC/MCAssembler.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #include "llvm/MC/MCAssembler.h" |
11 | | #include "llvm/ADT/ArrayRef.h" |
12 | | #include "llvm/ADT/SmallString.h" |
13 | | #include "llvm/ADT/SmallVector.h" |
14 | | #include "llvm/ADT/Statistic.h" |
15 | | #include "llvm/ADT/StringRef.h" |
16 | | #include "llvm/ADT/Twine.h" |
17 | | #include "llvm/MC/MCAsmBackend.h" |
18 | | #include "llvm/MC/MCAsmInfo.h" |
19 | | #include "llvm/MC/MCAsmLayout.h" |
20 | | #include "llvm/MC/MCCodeEmitter.h" |
21 | | #include "llvm/MC/MCCodeView.h" |
22 | | #include "llvm/MC/MCContext.h" |
23 | | #include "llvm/MC/MCDwarf.h" |
24 | | #include "llvm/MC/MCExpr.h" |
25 | | #include "llvm/MC/MCFixup.h" |
26 | | #include "llvm/MC/MCFixupKindInfo.h" |
27 | | #include "llvm/MC/MCFragment.h" |
28 | | #include "llvm/MC/MCInst.h" |
29 | | #include "llvm/MC/MCObjectWriter.h" |
30 | | #include "llvm/MC/MCSection.h" |
31 | | #include "llvm/MC/MCSectionELF.h" |
32 | | #include "llvm/MC/MCSymbol.h" |
33 | | #include "llvm/MC/MCValue.h" |
34 | | #include "llvm/Support/Casting.h" |
35 | | #include "llvm/Support/Debug.h" |
36 | | #include "llvm/Support/ErrorHandling.h" |
37 | | #include "llvm/Support/LEB128.h" |
38 | | #include "llvm/Support/MathExtras.h" |
39 | | #include "llvm/Support/raw_ostream.h" |
40 | | #include <cassert> |
41 | | #include <cstdint> |
42 | | #include <cstring> |
43 | | #include <tuple> |
44 | | #include <utility> |
45 | | |
46 | | using namespace llvm; |
47 | | |
48 | | #define DEBUG_TYPE "assembler" |
49 | | |
50 | | namespace { |
51 | | namespace stats { |
52 | | |
53 | | STATISTIC(EmittedFragments, "Number of emitted assembler fragments - total"); |
54 | | STATISTIC(EmittedRelaxableFragments, |
55 | | "Number of emitted assembler fragments - relaxable"); |
56 | | STATISTIC(EmittedDataFragments, |
57 | | "Number of emitted assembler fragments - data"); |
58 | | STATISTIC(EmittedCompactEncodedInstFragments, |
59 | | "Number of emitted assembler fragments - compact encoded inst"); |
60 | | STATISTIC(EmittedAlignFragments, |
61 | | "Number of emitted assembler fragments - align"); |
62 | | STATISTIC(EmittedFillFragments, |
63 | | "Number of emitted assembler fragments - fill"); |
64 | | STATISTIC(EmittedOrgFragments, |
65 | | "Number of emitted assembler fragments - org"); |
66 | | STATISTIC(evaluateFixup, "Number of evaluated fixups"); |
67 | | STATISTIC(FragmentLayouts, "Number of fragment layouts"); |
68 | | STATISTIC(ObjectBytes, "Number of emitted object file bytes"); |
69 | | STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps"); |
70 | | STATISTIC(RelaxedInstructions, "Number of relaxed instructions"); |
71 | | |
72 | | } // end namespace stats |
73 | | } // end anonymous namespace |
74 | | |
75 | | // FIXME FIXME FIXME: There are number of places in this file where we convert |
76 | | // what is a 64-bit assembler value used for computation into a value in the |
77 | | // object file, which may truncate it. We should detect that truncation where |
78 | | // invalid and report errors back. |
79 | | |
80 | | /* *** */ |
81 | | |
82 | | MCAssembler::MCAssembler(MCContext &Context, MCAsmBackend &Backend, |
83 | | MCCodeEmitter &Emitter, MCObjectWriter &Writer) |
84 | | : Context(Context), Backend(Backend), Emitter(Emitter), Writer(Writer), |
85 | | BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false), |
86 | 21.4k | IncrementalLinkerCompatible(false), ELFHeaderEFlags(0) { |
87 | 21.4k | VersionMinInfo.Major = 0; // Major version == 0 for "none specified" |
88 | 21.4k | } |
89 | | |
90 | 21.4k | MCAssembler::~MCAssembler() = default; |
91 | | |
92 | 18.0k | void MCAssembler::reset() { |
93 | 18.0k | Sections.clear(); |
94 | 18.0k | Symbols.clear(); |
95 | 18.0k | IndirectSymbols.clear(); |
96 | 18.0k | DataRegions.clear(); |
97 | 18.0k | LinkerOptions.clear(); |
98 | 18.0k | FileNames.clear(); |
99 | 18.0k | ThumbFuncs.clear(); |
100 | 18.0k | BundleAlignSize = 0; |
101 | 18.0k | RelaxAll = false; |
102 | 18.0k | SubsectionsViaSymbols = false; |
103 | 18.0k | IncrementalLinkerCompatible = false; |
104 | 18.0k | ELFHeaderEFlags = 0; |
105 | 18.0k | LOHContainer.reset(); |
106 | 18.0k | VersionMinInfo.Major = 0; |
107 | 18.0k | |
108 | 18.0k | // reset objects owned by us |
109 | 18.0k | getBackend().reset(); |
110 | 18.0k | getEmitter().reset(); |
111 | 18.0k | getWriter().reset(); |
112 | 18.0k | getLOHContainer().reset(); |
113 | 18.0k | } |
114 | | |
115 | 539k | bool MCAssembler::registerSection(MCSection &Section) { |
116 | 539k | if (Section.isRegistered()) |
117 | 119k | return false; |
118 | 420k | Sections.push_back(&Section); |
119 | 420k | Section.setIsRegistered(true); |
120 | 420k | return true; |
121 | 420k | } |
122 | | |
123 | 639k | bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const { |
124 | 639k | if (ThumbFuncs.count(Symbol)) |
125 | 2.13k | return true; |
126 | 637k | |
127 | 637k | if (637k !Symbol->isVariable()637k ) |
128 | 636k | return false; |
129 | 326 | |
130 | 326 | const MCExpr *Expr = Symbol->getVariableValue(); |
131 | 326 | |
132 | 326 | MCValue V; |
133 | 326 | if (!Expr->evaluateAsRelocatable(V, nullptr, nullptr)) |
134 | 1 | return false; |
135 | 325 | |
136 | 325 | if (325 V.getSymB() || 325 V.getRefKind() != MCSymbolRefExpr::VK_None316 ) |
137 | 10 | return false; |
138 | 315 | |
139 | 315 | const MCSymbolRefExpr *Ref = V.getSymA(); |
140 | 315 | if (!Ref) |
141 | 160 | return false; |
142 | 155 | |
143 | 155 | if (155 Ref->getKind() != MCSymbolRefExpr::VK_None155 ) |
144 | 0 | return false; |
145 | 155 | |
146 | 155 | const MCSymbol &Sym = Ref->getSymbol(); |
147 | 155 | if (!isThumbFunc(&Sym)) |
148 | 152 | return false; |
149 | 3 | |
150 | 3 | ThumbFuncs.insert(Symbol); // Cache it. |
151 | 3 | return true; |
152 | 3 | } |
153 | | |
154 | 38.4M | bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { |
155 | 38.4M | // Non-temporary labels should always be visible to the linker. |
156 | 38.4M | if (!Symbol.isTemporary()) |
157 | 12.0M | return true; |
158 | 26.4M | |
159 | 26.4M | // Absolute temporary labels are never visible. |
160 | 26.4M | if (26.4M !Symbol.isInSection()26.4M ) |
161 | 5.82M | return false; |
162 | 20.6M | |
163 | 20.6M | if (20.6M Symbol.isUsedInReloc()20.6M ) |
164 | 78 | return true; |
165 | 20.6M | |
166 | 20.6M | return false; |
167 | 20.6M | } |
168 | | |
169 | 4.93M | const MCSymbol *MCAssembler::getAtom(const MCSymbol &S) const { |
170 | 4.93M | // Linker visible symbols define atoms. |
171 | 4.93M | if (isSymbolLinkerVisible(S)) |
172 | 4.82M | return &S; |
173 | 112k | |
174 | 112k | // Absolute and undefined symbols have no defining atom. |
175 | 112k | if (112k !S.isInSection()112k ) |
176 | 4.63k | return nullptr; |
177 | 108k | |
178 | 108k | // Non-linker visible symbols in sections which can't be atomized have no |
179 | 108k | // defining atom. |
180 | 108k | if (108k !getContext().getAsmInfo()->isSectionAtomizableBySymbols( |
181 | 108k | *S.getFragment()->getParent())) |
182 | 7.69k | return nullptr; |
183 | 100k | |
184 | 100k | // Otherwise, return the atom for the containing fragment. |
185 | 100k | return S.getFragment()->getAtom(); |
186 | 100k | } |
187 | | |
188 | | bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, |
189 | | const MCFixup &Fixup, const MCFragment *DF, |
190 | 7.84M | MCValue &Target, uint64_t &Value) const { |
191 | 7.84M | ++stats::evaluateFixup; |
192 | 7.84M | |
193 | 7.84M | // FIXME: This code has some duplication with recordRelocation. We should |
194 | 7.84M | // probably merge the two into a single callback that tries to evaluate a |
195 | 7.84M | // fixup and records a relocation if one is needed. |
196 | 7.84M | |
197 | 7.84M | // On error claim to have completely evaluated the fixup, to prevent any |
198 | 7.84M | // further processing from being done. |
199 | 7.84M | const MCExpr *Expr = Fixup.getValue(); |
200 | 7.84M | MCContext &Ctx = getContext(); |
201 | 7.84M | Value = 0; |
202 | 7.84M | if (!Expr->evaluateAsRelocatable(Target, &Layout, &Fixup)7.84M ) { |
203 | 12 | Ctx.reportError(Fixup.getLoc(), "expected relocatable expression"); |
204 | 12 | return true; |
205 | 12 | } |
206 | 7.84M | if (const MCSymbolRefExpr *7.84M RefB7.84M = Target.getSymB()) { |
207 | 30.2k | if (RefB->getKind() != MCSymbolRefExpr::VK_None30.2k ) { |
208 | 6 | Ctx.reportError(Fixup.getLoc(), |
209 | 6 | "unsupported subtraction of qualified symbol"); |
210 | 6 | return true; |
211 | 6 | } |
212 | 7.84M | } |
213 | 7.84M | |
214 | 7.84M | bool IsPCRel = Backend.getFixupKindInfo( |
215 | 7.84M | Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel; |
216 | 7.84M | |
217 | 7.84M | bool IsResolved; |
218 | 7.84M | if (IsPCRel7.84M ) { |
219 | 6.06M | if (Target.getSymB()6.06M ) { |
220 | 5 | IsResolved = false; |
221 | 6.06M | } else if (6.06M !Target.getSymA()6.06M ) { |
222 | 13 | IsResolved = false; |
223 | 6.06M | } else { |
224 | 6.06M | const MCSymbolRefExpr *A = Target.getSymA(); |
225 | 6.06M | const MCSymbol &SA = A->getSymbol(); |
226 | 6.06M | if (A->getKind() != MCSymbolRefExpr::VK_None || 6.06M SA.isUndefined()4.82M ) { |
227 | 1.96M | IsResolved = false; |
228 | 6.06M | } else { |
229 | 4.10M | IsResolved = getWriter().isSymbolRefDifferenceFullyResolvedImpl( |
230 | 4.10M | *this, SA, *DF, false, true); |
231 | 4.10M | } |
232 | 6.06M | } |
233 | 7.84M | } else { |
234 | 1.78M | IsResolved = Target.isAbsolute(); |
235 | 1.78M | } |
236 | 7.84M | |
237 | 7.84M | Value = Target.getConstant(); |
238 | 7.84M | |
239 | 7.84M | if (const MCSymbolRefExpr *A7.84M = Target.getSymA()) { |
240 | 7.67M | const MCSymbol &Sym = A->getSymbol(); |
241 | 7.67M | if (Sym.isDefined()) |
242 | 6.77M | Value += Layout.getSymbolOffset(Sym); |
243 | 7.67M | } |
244 | 7.84M | if (const MCSymbolRefExpr *B7.84M = Target.getSymB()) { |
245 | 30.2k | const MCSymbol &Sym = B->getSymbol(); |
246 | 30.2k | if (Sym.isDefined()) |
247 | 30.2k | Value -= Layout.getSymbolOffset(Sym); |
248 | 30.2k | } |
249 | 7.84M | |
250 | 7.84M | bool ShouldAlignPC = Backend.getFixupKindInfo(Fixup.getKind()).Flags & |
251 | 7.84M | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits; |
252 | 7.84M | assert((ShouldAlignPC ? IsPCRel : true) && |
253 | 7.84M | "FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!"); |
254 | 7.84M | |
255 | 7.84M | if (IsPCRel7.84M ) { |
256 | 6.06M | uint32_t Offset = Layout.getFragmentOffset(DF) + Fixup.getOffset(); |
257 | 6.06M | |
258 | 6.06M | // A number of ARM fixups in Thumb mode require that the effective PC |
259 | 6.06M | // address be determined as the 32-bit aligned version of the actual offset. |
260 | 6.06M | if (ShouldAlignPC6.06M ) Offset &= ~0x35.81M ; |
261 | 6.06M | Value -= Offset; |
262 | 6.06M | } |
263 | 7.84M | |
264 | 7.84M | // Let the backend force a relocation if needed. |
265 | 7.84M | if (IsResolved && 7.84M Backend.shouldForceRelocation(*this, Fixup, Target)2.81M ) |
266 | 77 | IsResolved = false; |
267 | 7.84M | |
268 | 7.84M | return IsResolved; |
269 | 7.84M | } |
270 | | |
271 | | uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, |
272 | 9.22M | const MCFragment &F) const { |
273 | 9.22M | switch (F.getKind()) { |
274 | 5.44M | case MCFragment::FT_Data: |
275 | 5.44M | return cast<MCDataFragment>(F).getContents().size(); |
276 | 177k | case MCFragment::FT_Relaxable: |
277 | 177k | return cast<MCRelaxableFragment>(F).getContents().size(); |
278 | 396 | case MCFragment::FT_CompactEncodedInst: |
279 | 396 | return cast<MCCompactEncodedInstFragment>(F).getContents().size(); |
280 | 1.98M | case MCFragment::FT_Fill: |
281 | 1.98M | return cast<MCFillFragment>(F).getSize(); |
282 | 9.22M | |
283 | 6 | case MCFragment::FT_LEB: |
284 | 6 | return cast<MCLEBFragment>(F).getContents().size(); |
285 | 9.22M | |
286 | 3 | case MCFragment::FT_SafeSEH: |
287 | 3 | return 4; |
288 | 9.22M | |
289 | 1.54M | case MCFragment::FT_Align: { |
290 | 1.54M | const MCAlignFragment &AF = cast<MCAlignFragment>(F); |
291 | 1.54M | unsigned Offset = Layout.getFragmentOffset(&AF); |
292 | 1.54M | unsigned Size = OffsetToAlignment(Offset, AF.getAlignment()); |
293 | 1.54M | // If we are padding with nops, force the padding to be larger than the |
294 | 1.54M | // minimum nop size. |
295 | 1.54M | if (Size > 0 && 1.54M AF.hasEmitNops()326k ) { |
296 | 34.4k | while (Size % getBackend().getMinimumNopSize()) |
297 | 0 | Size += AF.getAlignment(); |
298 | 34.4k | } |
299 | 1.54M | if (Size > AF.getMaxBytesToEmit()) |
300 | 9 | return 0; |
301 | 1.54M | return Size; |
302 | 1.54M | } |
303 | 1.54M | |
304 | 40 | case MCFragment::FT_Org: { |
305 | 40 | const MCOrgFragment &OF = cast<MCOrgFragment>(F); |
306 | 40 | MCValue Value; |
307 | 40 | if (!OF.getOffset().evaluateAsValue(Value, Layout)40 ) { |
308 | 2 | getContext().reportError(OF.getLoc(), |
309 | 2 | "expected assembly-time absolute expression"); |
310 | 2 | return 0; |
311 | 2 | } |
312 | 38 | |
313 | 38 | uint64_t FragmentOffset = Layout.getFragmentOffset(&OF); |
314 | 38 | int64_t TargetLocation = Value.getConstant(); |
315 | 38 | if (const MCSymbolRefExpr *A38 = Value.getSymA()) { |
316 | 15 | uint64_t Val; |
317 | 15 | if (!Layout.getSymbolOffset(A->getSymbol(), Val)15 ) { |
318 | 4 | getContext().reportError(OF.getLoc(), "expected absolute expression"); |
319 | 4 | return 0; |
320 | 4 | } |
321 | 11 | TargetLocation += Val; |
322 | 11 | } |
323 | 34 | int64_t Size = TargetLocation - FragmentOffset; |
324 | 34 | if (Size < 0 || 34 Size >= 0x4000000030 ) { |
325 | 4 | getContext().reportError( |
326 | 4 | OF.getLoc(), "invalid .org offset '" + Twine(TargetLocation) + |
327 | 4 | "' (at offset '" + Twine(FragmentOffset) + "')"); |
328 | 4 | return 0; |
329 | 4 | } |
330 | 30 | return Size; |
331 | 30 | } |
332 | 30 | |
333 | 80.1k | case MCFragment::FT_Dwarf: |
334 | 80.1k | return cast<MCDwarfLineAddrFragment>(F).getContents().size(); |
335 | 776 | case MCFragment::FT_DwarfFrame: |
336 | 776 | return cast<MCDwarfCallFrameFragment>(F).getContents().size(); |
337 | 44 | case MCFragment::FT_CVInlineLines: |
338 | 44 | return cast<MCCVInlineLineTableFragment>(F).getContents().size(); |
339 | 212 | case MCFragment::FT_CVDefRange: |
340 | 212 | return cast<MCCVDefRangeFragment>(F).getContents().size(); |
341 | 0 | case MCFragment::FT_Dummy: |
342 | 0 | llvm_unreachable("Should not have been added"); |
343 | 0 | } |
344 | 0 |
|
345 | 0 | llvm_unreachable0 ("invalid fragment kind"); |
346 | 0 | } |
347 | | |
348 | 4.38M | void MCAsmLayout::layoutFragment(MCFragment *F) { |
349 | 4.38M | MCFragment *Prev = F->getPrevNode(); |
350 | 4.38M | |
351 | 4.38M | // We should never try to recompute something which is valid. |
352 | 4.38M | assert(!isFragmentValid(F) && "Attempt to recompute a valid fragment!"); |
353 | 4.38M | // We should never try to compute the fragment layout if its predecessor |
354 | 4.38M | // isn't valid. |
355 | 4.38M | assert((!Prev || isFragmentValid(Prev)) && |
356 | 4.38M | "Attempt to compute fragment before its predecessor!"); |
357 | 4.38M | |
358 | 4.38M | ++stats::FragmentLayouts; |
359 | 4.38M | |
360 | 4.38M | // Compute fragment offset and size. |
361 | 4.38M | if (Prev) |
362 | 3.96M | F->Offset = Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev); |
363 | 4.38M | else |
364 | 420k | F->Offset = 0; |
365 | 4.38M | LastValidFragment[F->getParent()] = F; |
366 | 4.38M | |
367 | 4.38M | // If bundling is enabled and this fragment has instructions in it, it has to |
368 | 4.38M | // obey the bundling restrictions. With padding, we'll have: |
369 | 4.38M | // |
370 | 4.38M | // |
371 | 4.38M | // BundlePadding |
372 | 4.38M | // ||| |
373 | 4.38M | // ------------------------------------- |
374 | 4.38M | // Prev |##########| F | |
375 | 4.38M | // ------------------------------------- |
376 | 4.38M | // ^ |
377 | 4.38M | // | |
378 | 4.38M | // F->Offset |
379 | 4.38M | // |
380 | 4.38M | // The fragment's offset will point to after the padding, and its computed |
381 | 4.38M | // size won't include the padding. |
382 | 4.38M | // |
383 | 4.38M | // When the -mc-relax-all flag is used, we optimize bundling by writting the |
384 | 4.38M | // padding directly into fragments when the instructions are emitted inside |
385 | 4.38M | // the streamer. When the fragment is larger than the bundle size, we need to |
386 | 4.38M | // ensure that it's bundle aligned. This means that if we end up with |
387 | 4.38M | // multiple fragments, we must emit bundle padding between fragments. |
388 | 4.38M | // |
389 | 4.38M | // ".align N" is an example of a directive that introduces multiple |
390 | 4.38M | // fragments. We could add a special case to handle ".align N" by emitting |
391 | 4.38M | // within-fragment padding (which would produce less padding when N is less |
392 | 4.38M | // than the bundle size), but for now we don't. |
393 | 4.38M | // |
394 | 4.38M | if (Assembler.isBundlingEnabled() && 4.38M F->hasInstructions()1.85k ) { |
395 | 752 | assert(isa<MCEncodedFragment>(F) && |
396 | 752 | "Only MCEncodedFragment implementations have instructions"); |
397 | 752 | uint64_t FSize = Assembler.computeFragmentSize(*this, *F); |
398 | 752 | |
399 | 752 | if (!Assembler.getRelaxAll() && 752 FSize > Assembler.getBundleAlignSize()732 ) |
400 | 1 | report_fatal_error("Fragment can't be larger than a bundle size"); |
401 | 751 | |
402 | 751 | uint64_t RequiredBundlePadding = computeBundlePadding(Assembler, F, |
403 | 751 | F->Offset, FSize); |
404 | 751 | if (RequiredBundlePadding > UINT8_MAX) |
405 | 0 | report_fatal_error("Padding cannot exceed 255 bytes"); |
406 | 751 | F->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding)); |
407 | 751 | F->Offset += RequiredBundlePadding; |
408 | 751 | } |
409 | 4.38M | } |
410 | | |
411 | 16.1M | void MCAssembler::registerSymbol(const MCSymbol &Symbol, bool *Created) { |
412 | 16.1M | bool New = !Symbol.isRegistered(); |
413 | 16.1M | if (Created) |
414 | 11 | *Created = New; |
415 | 16.1M | if (New16.1M ) { |
416 | 7.15M | Symbol.setIsRegistered(true); |
417 | 7.15M | Symbols.push_back(&Symbol); |
418 | 7.15M | } |
419 | 16.1M | } |
420 | | |
421 | | void MCAssembler::writeFragmentPadding(const MCFragment &F, uint64_t FSize, |
422 | 4.26M | MCObjectWriter *OW) const { |
423 | 4.26M | // Should NOP padding be written out before this fragment? |
424 | 4.26M | unsigned BundlePadding = F.getBundlePadding(); |
425 | 4.26M | if (BundlePadding > 04.26M ) { |
426 | 430 | assert(isBundlingEnabled() && |
427 | 430 | "Writing bundle padding with disabled bundling"); |
428 | 430 | assert(F.hasInstructions() && |
429 | 430 | "Writing bundle padding for a fragment without instructions"); |
430 | 430 | |
431 | 430 | unsigned TotalLength = BundlePadding + static_cast<unsigned>(FSize); |
432 | 430 | if (F.alignToBundleEnd() && 430 TotalLength > getBundleAlignSize()269 ) { |
433 | 128 | // If the padding itself crosses a bundle boundary, it must be emitted |
434 | 128 | // in 2 pieces, since even nop instructions must not cross boundaries. |
435 | 128 | // v--------------v <- BundleAlignSize |
436 | 128 | // v---------v <- BundlePadding |
437 | 128 | // ---------------------------- |
438 | 128 | // | Prev |####|####| F | |
439 | 128 | // ---------------------------- |
440 | 128 | // ^-------------------^ <- TotalLength |
441 | 128 | unsigned DistanceToBoundary = TotalLength - getBundleAlignSize(); |
442 | 128 | if (!getBackend().writeNopData(DistanceToBoundary, OW)) |
443 | 0 | report_fatal_error("unable to write NOP sequence of " + |
444 | 0 | Twine(DistanceToBoundary) + " bytes"); |
445 | 128 | BundlePadding -= DistanceToBoundary; |
446 | 128 | } |
447 | 430 | if (430 !getBackend().writeNopData(BundlePadding, OW)430 ) |
448 | 0 | report_fatal_error("unable to write NOP sequence of " + |
449 | 0 | Twine(BundlePadding) + " bytes"); |
450 | 4.26M | } |
451 | 4.26M | } |
452 | | |
453 | | /// \brief Write the fragment \p F to the output file. |
454 | | static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, |
455 | 4.26M | const MCFragment &F) { |
456 | 4.26M | MCObjectWriter *OW = &Asm.getWriter(); |
457 | 4.26M | |
458 | 4.26M | // FIXME: Embed in fragments instead? |
459 | 4.26M | uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F); |
460 | 4.26M | |
461 | 4.26M | Asm.writeFragmentPadding(F, FragmentSize, OW); |
462 | 4.26M | |
463 | 4.26M | // This variable (and its dummy usage) is to participate in the assert at |
464 | 4.26M | // the end of the function. |
465 | 4.26M | uint64_t Start = OW->getStream().tell(); |
466 | 4.26M | (void) Start; |
467 | 4.26M | |
468 | 4.26M | ++stats::EmittedFragments; |
469 | 4.26M | |
470 | 4.26M | switch (F.getKind()) { |
471 | 759k | case MCFragment::FT_Align: { |
472 | 759k | ++stats::EmittedAlignFragments; |
473 | 759k | const MCAlignFragment &AF = cast<MCAlignFragment>(F); |
474 | 759k | assert(AF.getValueSize() && "Invalid virtual align in concrete fragment!"); |
475 | 759k | |
476 | 759k | uint64_t Count = FragmentSize / AF.getValueSize(); |
477 | 759k | |
478 | 759k | // FIXME: This error shouldn't actually occur (the front end should emit |
479 | 759k | // multiple .align directives to enforce the semantics it wants), but is |
480 | 759k | // severe enough that we want to report it. How to handle this? |
481 | 759k | if (Count * AF.getValueSize() != FragmentSize) |
482 | 0 | report_fatal_error("undefined .align directive, value size '" + |
483 | 0 | Twine(AF.getValueSize()) + |
484 | 0 | "' is not a divisor of padding size '" + |
485 | 0 | Twine(FragmentSize) + "'"); |
486 | 759k | |
487 | 759k | // See if we are aligning with nops, and if so do that first to try to fill |
488 | 759k | // the Count bytes. Then if that did not fill any bytes or there are any |
489 | 759k | // bytes left to fill use the Value and ValueSize to fill the rest. |
490 | 759k | // If we are aligning with nops, ask that target to emit the right data. |
491 | 759k | if (759k AF.hasEmitNops()759k ) { |
492 | 475k | if (!Asm.getBackend().writeNopData(Count, OW)) |
493 | 0 | report_fatal_error("unable to write nop sequence of " + |
494 | 0 | Twine(Count) + " bytes"); |
495 | 475k | break; |
496 | 475k | } |
497 | 284k | |
498 | 284k | // Otherwise, write out in multiples of the value size. |
499 | 3.15M | for (uint64_t i = 0; 284k i != Count3.15M ; ++i2.87M ) { |
500 | 2.87M | switch (AF.getValueSize()) { |
501 | 0 | default: 0 llvm_unreachable0 ("Invalid size!"); |
502 | 2.87M | case 1: OW->write8 (uint8_t (AF.getValue())); break; |
503 | 3 | case 2: OW->write16(uint16_t(AF.getValue())); break; |
504 | 0 | case 4: OW->write32(uint32_t(AF.getValue())); break; |
505 | 0 | case 8: OW->write64(uint64_t(AF.getValue())); break; |
506 | 2.87M | } |
507 | 2.87M | } |
508 | 284k | break; |
509 | 284k | } |
510 | 284k | |
511 | 2.47M | case MCFragment::FT_Data: |
512 | 2.47M | ++stats::EmittedDataFragments; |
513 | 2.47M | OW->writeBytes(cast<MCDataFragment>(F).getContents()); |
514 | 2.47M | break; |
515 | 284k | |
516 | 65.0k | case MCFragment::FT_Relaxable: |
517 | 65.0k | ++stats::EmittedRelaxableFragments; |
518 | 65.0k | OW->writeBytes(cast<MCRelaxableFragment>(F).getContents()); |
519 | 65.0k | break; |
520 | 284k | |
521 | 131 | case MCFragment::FT_CompactEncodedInst: |
522 | 131 | ++stats::EmittedCompactEncodedInstFragments; |
523 | 131 | OW->writeBytes(cast<MCCompactEncodedInstFragment>(F).getContents()); |
524 | 131 | break; |
525 | 284k | |
526 | 928k | case MCFragment::FT_Fill: { |
527 | 928k | ++stats::EmittedFillFragments; |
528 | 928k | const MCFillFragment &FF = cast<MCFillFragment>(F); |
529 | 928k | uint8_t V = FF.getValue(); |
530 | 928k | const unsigned MaxChunkSize = 16; |
531 | 928k | char Data[MaxChunkSize]; |
532 | 928k | memcpy(Data, &V, 1); |
533 | 14.8M | for (unsigned I = 1; I < MaxChunkSize14.8M ; ++I13.9M ) |
534 | 13.9M | Data[I] = Data[0]; |
535 | 928k | |
536 | 928k | uint64_t Size = FF.getSize(); |
537 | 5.57M | for (unsigned ChunkSize = MaxChunkSize; ChunkSize5.57M ; ChunkSize /= 24.64M ) { |
538 | 4.64M | StringRef Ref(Data, ChunkSize); |
539 | 49.4M | for (uint64_t I = 0, E = Size / ChunkSize; I != E49.4M ; ++I44.7M ) |
540 | 44.7M | OW->writeBytes(Ref); |
541 | 4.64M | Size = Size % ChunkSize; |
542 | 4.64M | } |
543 | 928k | break; |
544 | 284k | } |
545 | 284k | |
546 | 2 | case MCFragment::FT_LEB: { |
547 | 2 | const MCLEBFragment &LF = cast<MCLEBFragment>(F); |
548 | 2 | OW->writeBytes(LF.getContents()); |
549 | 2 | break; |
550 | 284k | } |
551 | 284k | |
552 | 1 | case MCFragment::FT_SafeSEH: { |
553 | 1 | const MCSafeSEHFragment &SF = cast<MCSafeSEHFragment>(F); |
554 | 1 | OW->write32(SF.getSymbol()->getIndex()); |
555 | 1 | break; |
556 | 284k | } |
557 | 284k | |
558 | 19 | case MCFragment::FT_Org: { |
559 | 19 | ++stats::EmittedOrgFragments; |
560 | 19 | const MCOrgFragment &OF = cast<MCOrgFragment>(F); |
561 | 19 | |
562 | 2.48k | for (uint64_t i = 0, e = FragmentSize; i != e2.48k ; ++i2.46k ) |
563 | 2.46k | OW->write8(uint8_t(OF.getValue())); |
564 | 19 | |
565 | 19 | break; |
566 | 284k | } |
567 | 284k | |
568 | 40.0k | case MCFragment::FT_Dwarf: { |
569 | 40.0k | const MCDwarfLineAddrFragment &OF = cast<MCDwarfLineAddrFragment>(F); |
570 | 40.0k | OW->writeBytes(OF.getContents()); |
571 | 40.0k | break; |
572 | 284k | } |
573 | 388 | case MCFragment::FT_DwarfFrame: { |
574 | 388 | const MCDwarfCallFrameFragment &CF = cast<MCDwarfCallFrameFragment>(F); |
575 | 388 | OW->writeBytes(CF.getContents()); |
576 | 388 | break; |
577 | 284k | } |
578 | 22 | case MCFragment::FT_CVInlineLines: { |
579 | 22 | const auto &OF = cast<MCCVInlineLineTableFragment>(F); |
580 | 22 | OW->writeBytes(OF.getContents()); |
581 | 22 | break; |
582 | 284k | } |
583 | 106 | case MCFragment::FT_CVDefRange: { |
584 | 106 | const auto &DRF = cast<MCCVDefRangeFragment>(F); |
585 | 106 | OW->writeBytes(DRF.getContents()); |
586 | 106 | break; |
587 | 284k | } |
588 | 0 | case MCFragment::FT_Dummy: |
589 | 0 | llvm_unreachable("Should not have been added"); |
590 | 4.26M | } |
591 | 4.26M | |
592 | 4.26M | assert(OW->getStream().tell() - Start == FragmentSize && |
593 | 4.26M | "The stream should advance by fragment size"); |
594 | 4.26M | } |
595 | | |
596 | | void MCAssembler::writeSectionData(const MCSection *Sec, |
597 | 419k | const MCAsmLayout &Layout) const { |
598 | 419k | // Ignore virtual sections. |
599 | 419k | if (Sec->isVirtualSection()419k ) { |
600 | 5.04k | assert(Layout.getSectionFileSize(Sec) == 0 && "Invalid size for section!"); |
601 | 5.04k | |
602 | 5.04k | // Check that contents are only things legal inside a virtual section. |
603 | 13.5k | for (const MCFragment &F : *Sec) { |
604 | 13.5k | switch (F.getKind()) { |
605 | 0 | default: 0 llvm_unreachable0 ("Invalid fragment in virtual section!"); |
606 | 816 | case MCFragment::FT_Data: { |
607 | 816 | // Check that we aren't trying to write a non-zero contents (or fixups) |
608 | 816 | // into a virtual section. This is to support clients which use standard |
609 | 816 | // directives to fill the contents of virtual sections. |
610 | 816 | const MCDataFragment &DF = cast<MCDataFragment>(F); |
611 | 816 | if (DF.fixup_begin() != DF.fixup_end()) |
612 | 1 | report_fatal_error("cannot have fixups in virtual section!"); |
613 | 1.43k | for (unsigned i = 0, e = DF.getContents().size(); 815 i != e1.43k ; ++i620 ) |
614 | 621 | if (621 DF.getContents()[i]621 ) { |
615 | 1 | if (auto *ELFSec = dyn_cast<const MCSectionELF>(Sec)) |
616 | 1 | report_fatal_error("non-zero initializer found in section '" + |
617 | 1 | ELFSec->getSectionName() + "'"); |
618 | 1 | else |
619 | 0 | report_fatal_error("non-zero initializer found in virtual section"); |
620 | 621 | } |
621 | 814 | break; |
622 | 815 | } |
623 | 6.10k | case MCFragment::FT_Align: |
624 | 6.10k | // Check that we aren't trying to write a non-zero value into a virtual |
625 | 6.10k | // section. |
626 | 6.10k | assert((cast<MCAlignFragment>(F).getValueSize() == 0 || |
627 | 6.10k | cast<MCAlignFragment>(F).getValue() == 0) && |
628 | 6.10k | "Invalid align in virtual section!"); |
629 | 6.10k | break; |
630 | 6.60k | case MCFragment::FT_Fill: |
631 | 6.60k | assert((cast<MCFillFragment>(F).getValue() == 0) && |
632 | 6.60k | "Invalid fill in virtual section!"); |
633 | 6.60k | break; |
634 | 5.04k | } |
635 | 5.04k | } |
636 | 5.04k | |
637 | 5.04k | return; |
638 | 5.04k | } |
639 | 414k | |
640 | 414k | uint64_t Start = getWriter().getStream().tell(); |
641 | 414k | (void)Start; |
642 | 414k | |
643 | 414k | for (const MCFragment &F : *Sec) |
644 | 4.26M | writeFragment(*this, Layout, F); |
645 | 419k | |
646 | 419k | assert(getWriter().getStream().tell() - Start == |
647 | 419k | Layout.getSectionAddressSize(Sec)); |
648 | 419k | } |
649 | | |
650 | | std::tuple<MCValue, uint64_t, bool> |
651 | | MCAssembler::handleFixup(const MCAsmLayout &Layout, MCFragment &F, |
652 | 7.71M | const MCFixup &Fixup) { |
653 | 7.71M | // Evaluate the fixup. |
654 | 7.71M | MCValue Target; |
655 | 7.71M | uint64_t FixedValue; |
656 | 7.71M | bool IsResolved = evaluateFixup(Layout, Fixup, &F, Target, FixedValue); |
657 | 7.71M | if (!IsResolved7.71M ) { |
658 | 5.03M | // The fixup was unresolved, we need a relocation. Inform the object |
659 | 5.03M | // writer of the relocation, and give it an opportunity to adjust the |
660 | 5.03M | // fixup value if need be. |
661 | 5.03M | getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, FixedValue); |
662 | 5.03M | } |
663 | 7.71M | return std::make_tuple(Target, FixedValue, IsResolved); |
664 | 7.71M | } |
665 | | |
666 | 21.4k | void MCAssembler::layout(MCAsmLayout &Layout) { |
667 | 21.4k | DEBUG_WITH_TYPE("mc-dump", { |
668 | 21.4k | errs() << "assembler backend - pre-layout\n--\n"; |
669 | 21.4k | dump(); }); |
670 | 21.4k | |
671 | 21.4k | // Create dummy fragments and assign section ordinals. |
672 | 21.4k | unsigned SectionIndex = 0; |
673 | 420k | for (MCSection &Sec : *this) { |
674 | 420k | // Create dummy fragments to eliminate any empty sections, this simplifies |
675 | 420k | // layout. |
676 | 420k | if (Sec.getFragmentList().empty()) |
677 | 593 | new MCDataFragment(&Sec); |
678 | 420k | |
679 | 420k | Sec.setOrdinal(SectionIndex++); |
680 | 420k | } |
681 | 21.4k | |
682 | 21.4k | // Assign layout order indices to sections and fragments. |
683 | 441k | for (unsigned i = 0, e = Layout.getSectionOrder().size(); i != e441k ; ++i420k ) { |
684 | 420k | MCSection *Sec = Layout.getSectionOrder()[i]; |
685 | 420k | Sec->setLayoutOrder(i); |
686 | 420k | |
687 | 420k | unsigned FragmentIndex = 0; |
688 | 420k | for (MCFragment &Frag : *Sec) |
689 | 4.27M | Frag.setLayoutOrder(FragmentIndex++); |
690 | 420k | } |
691 | 21.4k | |
692 | 21.4k | // Layout until everything fits. |
693 | 22.5k | while (layoutOnce(Layout)) |
694 | 1.15k | if (1.15k getContext().hadError()1.15k ) |
695 | 0 | return; |
696 | 21.4k | |
697 | 21.4k | DEBUG_WITH_TYPE21.4k ("mc-dump", { |
698 | 21.4k | errs() << "assembler backend - post-relaxation\n--\n"; |
699 | 21.4k | dump(); }); |
700 | 21.4k | |
701 | 21.4k | // Finalize the layout, including fragment lowering. |
702 | 21.4k | finishLayout(Layout); |
703 | 21.4k | |
704 | 21.4k | DEBUG_WITH_TYPE("mc-dump", { |
705 | 21.4k | errs() << "assembler backend - final-layout\n--\n"; |
706 | 21.4k | dump(); }); |
707 | 21.4k | |
708 | 21.4k | // Allow the object writer a chance to perform post-layout binding (for |
709 | 21.4k | // example, to set the index fields in the symbol data). |
710 | 21.4k | getWriter().executePostLayoutBinding(*this, Layout); |
711 | 21.4k | |
712 | 21.4k | // Evaluate and apply the fixups, generating relocation entries as necessary. |
713 | 420k | for (MCSection &Sec : *this) { |
714 | 4.27M | for (MCFragment &Frag : Sec) { |
715 | 4.27M | // Data and relaxable fragments both have fixups. So only process |
716 | 4.27M | // those here. |
717 | 4.27M | // FIXME: Is there a better way to do this? MCEncodedFragmentWithFixups |
718 | 4.27M | // being templated makes this tricky. |
719 | 4.27M | if (isa<MCEncodedFragment>(&Frag) && |
720 | 2.53M | isa<MCCompactEncodedInstFragment>(&Frag)) |
721 | 131 | continue; |
722 | 4.27M | if (4.27M !isa<MCEncodedFragment>(&Frag) && 4.27M !isa<MCCVDefRangeFragment>(&Frag)1.74M ) |
723 | 1.74M | continue; |
724 | 2.53M | ArrayRef<MCFixup> Fixups; |
725 | 2.53M | MutableArrayRef<char> Contents; |
726 | 2.53M | if (auto *FragWithFixups2.53M = dyn_cast<MCDataFragment>(&Frag)) { |
727 | 2.47M | Fixups = FragWithFixups->getFixups(); |
728 | 2.47M | Contents = FragWithFixups->getContents(); |
729 | 2.53M | } else if (auto *65.1k FragWithFixups65.1k = dyn_cast<MCRelaxableFragment>(&Frag)) { |
730 | 65.0k | Fixups = FragWithFixups->getFixups(); |
731 | 65.0k | Contents = FragWithFixups->getContents(); |
732 | 65.1k | } else if (auto *106 FragWithFixups106 = dyn_cast<MCCVDefRangeFragment>(&Frag)) { |
733 | 106 | Fixups = FragWithFixups->getFixups(); |
734 | 106 | Contents = FragWithFixups->getContents(); |
735 | 106 | } else |
736 | 0 | llvm_unreachable("Unknown fragment with fixups!"); |
737 | 2.53M | for (const MCFixup &Fixup : Fixups) 2.53M { |
738 | 7.71M | uint64_t FixedValue; |
739 | 7.71M | bool IsResolved; |
740 | 7.71M | MCValue Target; |
741 | 7.71M | std::tie(Target, FixedValue, IsResolved) = |
742 | 7.71M | handleFixup(Layout, Frag, Fixup); |
743 | 7.71M | getBackend().applyFixup(*this, Fixup, Target, Contents, FixedValue, |
744 | 7.71M | IsResolved); |
745 | 7.71M | } |
746 | 4.27M | } |
747 | 420k | } |
748 | 21.4k | } |
749 | | |
750 | 21.3k | void MCAssembler::Finish() { |
751 | 21.3k | // Create the layout object. |
752 | 21.3k | MCAsmLayout Layout(*this); |
753 | 21.3k | layout(Layout); |
754 | 21.3k | |
755 | 21.3k | raw_ostream &OS = getWriter().getStream(); |
756 | 21.3k | uint64_t StartOffset = OS.tell(); |
757 | 21.3k | |
758 | 21.3k | // Write the object file. |
759 | 21.3k | getWriter().writeObject(*this, Layout); |
760 | 21.3k | |
761 | 21.3k | stats::ObjectBytes += OS.tell() - StartOffset; |
762 | 21.3k | } |
763 | | |
764 | | bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup, |
765 | | const MCRelaxableFragment *DF, |
766 | 136k | const MCAsmLayout &Layout) const { |
767 | 136k | MCValue Target; |
768 | 136k | uint64_t Value; |
769 | 136k | bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value); |
770 | 136k | if (Target.getSymA() && |
771 | 136k | Target.getSymA()->getKind() == MCSymbolRefExpr::VK_X86_ABS8 && |
772 | 2 | Fixup.getKind() == FK_Data_1) |
773 | 2 | return false; |
774 | 136k | return getBackend().fixupNeedsRelaxationAdvanced(Fixup, Resolved, Value, DF, |
775 | 136k | Layout); |
776 | 136k | } |
777 | | |
778 | | bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F, |
779 | 167k | const MCAsmLayout &Layout) const { |
780 | 167k | // If this inst doesn't ever need relaxation, ignore it. This occurs when we |
781 | 167k | // are intentionally pushing out inst fragments, or because we relaxed a |
782 | 167k | // previous instruction to one that doesn't need relaxation. |
783 | 167k | if (!getBackend().mayNeedRelaxation(F->getInst())) |
784 | 29.3k | return false; |
785 | 138k | |
786 | 138k | for (const MCFixup &Fixup : F->getFixups()) |
787 | 136k | if (136k fixupNeedsRelaxation(Fixup, F, Layout)136k ) |
788 | 11.8k | return true; |
789 | 126k | |
790 | 126k | return false; |
791 | 126k | } |
792 | | |
793 | | bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, |
794 | 167k | MCRelaxableFragment &F) { |
795 | 167k | if (!fragmentNeedsRelaxation(&F, Layout)) |
796 | 155k | return false; |
797 | 11.8k | |
798 | 11.8k | ++stats::RelaxedInstructions; |
799 | 11.8k | |
800 | 11.8k | // FIXME-PERF: We could immediately lower out instructions if we can tell |
801 | 11.8k | // they are fully resolved, to avoid retesting on later passes. |
802 | 11.8k | |
803 | 11.8k | // Relax the fragment. |
804 | 11.8k | |
805 | 11.8k | MCInst Relaxed; |
806 | 11.8k | getBackend().relaxInstruction(F.getInst(), F.getSubtargetInfo(), Relaxed); |
807 | 11.8k | |
808 | 11.8k | // Encode the new instruction. |
809 | 11.8k | // |
810 | 11.8k | // FIXME-PERF: If it matters, we could let the target do this. It can |
811 | 11.8k | // probably do so more efficiently in many cases. |
812 | 11.8k | SmallVector<MCFixup, 4> Fixups; |
813 | 11.8k | SmallString<256> Code; |
814 | 11.8k | raw_svector_ostream VecOS(Code); |
815 | 11.8k | getEmitter().encodeInstruction(Relaxed, VecOS, Fixups, F.getSubtargetInfo()); |
816 | 11.8k | |
817 | 11.8k | // Update the fragment. |
818 | 11.8k | F.setInst(Relaxed); |
819 | 11.8k | F.getContents() = Code; |
820 | 11.8k | F.getFixups() = Fixups; |
821 | 11.8k | |
822 | 11.8k | return true; |
823 | 11.8k | } |
824 | | |
825 | 7 | bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { |
826 | 7 | uint64_t OldSize = LF.getContents().size(); |
827 | 7 | int64_t Value; |
828 | 7 | bool Abs = LF.getValue().evaluateKnownAbsolute(Value, Layout); |
829 | 7 | if (!Abs) |
830 | 1 | report_fatal_error("sleb128 and uleb128 expressions must be absolute"); |
831 | 6 | SmallString<8> &Data = LF.getContents(); |
832 | 6 | Data.clear(); |
833 | 6 | raw_svector_ostream OSE(Data); |
834 | 6 | if (LF.isSigned()) |
835 | 3 | encodeSLEB128(Value, OSE); |
836 | 6 | else |
837 | 3 | encodeULEB128(Value, OSE); |
838 | 7 | return OldSize != LF.getContents().size(); |
839 | 7 | } |
840 | | |
841 | | bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, |
842 | 119k | MCDwarfLineAddrFragment &DF) { |
843 | 119k | MCContext &Context = Layout.getAssembler().getContext(); |
844 | 119k | uint64_t OldSize = DF.getContents().size(); |
845 | 119k | int64_t AddrDelta; |
846 | 119k | bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout); |
847 | 119k | assert(Abs && "We created a line delta with an invalid expression"); |
848 | 119k | (void) Abs; |
849 | 119k | int64_t LineDelta; |
850 | 119k | LineDelta = DF.getLineDelta(); |
851 | 119k | SmallString<8> &Data = DF.getContents(); |
852 | 119k | Data.clear(); |
853 | 119k | raw_svector_ostream OSE(Data); |
854 | 119k | MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta, |
855 | 119k | AddrDelta, OSE); |
856 | 119k | return OldSize != Data.size(); |
857 | 119k | } |
858 | | |
859 | | bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, |
860 | 752 | MCDwarfCallFrameFragment &DF) { |
861 | 752 | MCContext &Context = Layout.getAssembler().getContext(); |
862 | 752 | uint64_t OldSize = DF.getContents().size(); |
863 | 752 | int64_t AddrDelta; |
864 | 752 | bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout); |
865 | 752 | assert(Abs && "We created call frame with an invalid expression"); |
866 | 752 | (void) Abs; |
867 | 752 | SmallString<8> &Data = DF.getContents(); |
868 | 752 | Data.clear(); |
869 | 752 | raw_svector_ostream OSE(Data); |
870 | 752 | MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE); |
871 | 752 | return OldSize != Data.size(); |
872 | 752 | } |
873 | | |
874 | | bool MCAssembler::relaxCVInlineLineTable(MCAsmLayout &Layout, |
875 | 66 | MCCVInlineLineTableFragment &F) { |
876 | 66 | unsigned OldSize = F.getContents().size(); |
877 | 66 | getContext().getCVContext().encodeInlineLineTable(Layout, F); |
878 | 66 | return OldSize != F.getContents().size(); |
879 | 66 | } |
880 | | |
881 | | bool MCAssembler::relaxCVDefRange(MCAsmLayout &Layout, |
882 | 318 | MCCVDefRangeFragment &F) { |
883 | 318 | unsigned OldSize = F.getContents().size(); |
884 | 318 | getContext().getCVContext().encodeDefRange(Layout, F); |
885 | 318 | return OldSize != F.getContents().size(); |
886 | 318 | } |
887 | | |
888 | 432k | bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) { |
889 | 432k | // Holds the first fragment which needed relaxing during this layout. It will |
890 | 432k | // remain NULL if none were relaxed. |
891 | 432k | // When a fragment is relaxed, all the fragments following it should get |
892 | 432k | // invalidated because their offset is going to change. |
893 | 432k | MCFragment *FirstRelaxedFragment = nullptr; |
894 | 432k | |
895 | 432k | // Attempt to relax all the fragments in the section. |
896 | 5.15M | for (MCSection::iterator I = Sec.begin(), IE = Sec.end(); I != IE5.15M ; ++I4.72M ) { |
897 | 4.72M | // Check if this is a fragment that needs relaxation. |
898 | 4.72M | bool RelaxedFrag = false; |
899 | 4.72M | switch(I->getKind()) { |
900 | 4.43M | default: |
901 | 4.43M | break; |
902 | 167k | case MCFragment::FT_Relaxable: |
903 | 167k | assert(!getRelaxAll() && |
904 | 167k | "Did not expect a MCRelaxableFragment in RelaxAll mode"); |
905 | 167k | RelaxedFrag = relaxInstruction(Layout, *cast<MCRelaxableFragment>(I)); |
906 | 167k | break; |
907 | 119k | case MCFragment::FT_Dwarf: |
908 | 119k | RelaxedFrag = relaxDwarfLineAddr(Layout, |
909 | 119k | *cast<MCDwarfLineAddrFragment>(I)); |
910 | 119k | break; |
911 | 752 | case MCFragment::FT_DwarfFrame: |
912 | 752 | RelaxedFrag = |
913 | 752 | relaxDwarfCallFrameFragment(Layout, |
914 | 752 | *cast<MCDwarfCallFrameFragment>(I)); |
915 | 752 | break; |
916 | 7 | case MCFragment::FT_LEB: |
917 | 7 | RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I)); |
918 | 7 | break; |
919 | 66 | case MCFragment::FT_CVInlineLines: |
920 | 66 | RelaxedFrag = |
921 | 66 | relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I)); |
922 | 66 | break; |
923 | 318 | case MCFragment::FT_CVDefRange: |
924 | 318 | RelaxedFrag = relaxCVDefRange(Layout, *cast<MCCVDefRangeFragment>(I)); |
925 | 318 | break; |
926 | 4.72M | } |
927 | 4.72M | if (4.72M RelaxedFrag && 4.72M !FirstRelaxedFragment35.4k ) |
928 | 1.65k | FirstRelaxedFragment = &*I; |
929 | 4.72M | } |
930 | 432k | if (432k FirstRelaxedFragment432k ) { |
931 | 1.65k | Layout.invalidateFragmentsFrom(FirstRelaxedFragment); |
932 | 1.65k | return true; |
933 | 1.65k | } |
934 | 430k | return false; |
935 | 430k | } |
936 | | |
937 | 22.5k | bool MCAssembler::layoutOnce(MCAsmLayout &Layout) { |
938 | 22.5k | ++stats::RelaxationSteps; |
939 | 22.5k | |
940 | 22.5k | bool WasRelaxed = false; |
941 | 453k | for (iterator it = begin(), ie = end(); it != ie453k ; ++it430k ) { |
942 | 430k | MCSection &Sec = *it; |
943 | 432k | while (layoutSectionOnce(Layout, Sec)) |
944 | 1.65k | WasRelaxed = true; |
945 | 430k | } |
946 | 22.5k | |
947 | 22.5k | return WasRelaxed; |
948 | 22.5k | } |
949 | | |
950 | 21.4k | void MCAssembler::finishLayout(MCAsmLayout &Layout) { |
951 | 21.4k | // The layout is done. Mark every fragment as valid. |
952 | 441k | for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n441k ; ++i420k ) { |
953 | 420k | MCSection &Section = *Layout.getSectionOrder()[i]; |
954 | 420k | Layout.getFragmentOffset(&*Section.rbegin()); |
955 | 420k | computeFragmentSize(Layout, *Section.rbegin()); |
956 | 420k | } |
957 | 21.4k | getBackend().finishLayout(*this, Layout); |
958 | 21.4k | } |