LLVM 24.0.0git
MCSFrame.cpp
Go to the documentation of this file.
1//===- lib/MC/MCSFrame.cpp - MCSFrame implementation ----------------------===//
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#include "llvm/MC/MCSFrame.h"
13#include "llvm/MC/MCAsmInfo.h"
14#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCSection.h"
18#include "llvm/MC/MCSymbol.h"
20
21using namespace llvm;
22using namespace sframe;
23
24namespace {
25
26// High-level structure to track info needed to emit a
27// sframe_frame_row_entry_addrX. On disk these have both a fixed portion of type
28// sframe_frame_row_entry_addrX and trailing data of X * S bytes, where X is the
29// datum size, and S is 1, 2, or 3 depending on which of CFA, SP, and FP are
30// being tracked.
31struct SFrameFRE {
32 // An FRE describes how to find the registers when the PC is at this
33 // Label from function start.
34 const MCSymbol *Label = nullptr;
35 size_t CFAOffset = 0;
36 size_t FPOffset = 0;
37 size_t RAOffset = 0;
38 FREInfo<endianness::native> Info;
39 bool CFARegSet = false;
40
41 SFrameFRE(const MCSymbol *Start) : Label(Start) { Info.Info = 0; }
42
43 void emitOffset(MCObjectStreamer &S, FREOffset OffsetSize, size_t Offset) {
44 switch (OffsetSize) {
45 case (FREOffset::B1):
47 return;
48 case (FREOffset::B2):
50 return;
51 case (FREOffset::B4):
53 return;
54 }
55 }
56
57 void emit(MCObjectStreamer &S, const MCSymbol *FuncBegin,
58 MCFragment *FDEFrag) {
59 S.emitSFrameCalculateFuncOffset(FuncBegin, Label, FDEFrag, SMLoc());
60
61 // fre_cfa_base_reg_id already set during parsing
62
63 // fre_offset_count
64 unsigned RegsTracked = 1; // always track the cfa.
65 if (FPOffset != 0)
66 ++RegsTracked;
67 if (RAOffset != 0)
68 ++RegsTracked;
69 Info.setOffsetCount(RegsTracked);
70
71 // fre_offset_size
72 if (isInt<8>(CFAOffset) && isInt<8>(FPOffset) && isInt<8>(RAOffset))
73 Info.setOffsetSize(FREOffset::B1);
74 else if (isInt<16>(CFAOffset) && isInt<16>(FPOffset) && isInt<16>(RAOffset))
75 Info.setOffsetSize(FREOffset::B2);
76 else {
77 assert(isInt<32>(CFAOffset) && isInt<32>(FPOffset) &&
78 isInt<32>(RAOffset) && "Offset too big for sframe");
79 Info.setOffsetSize(FREOffset::B4);
80 }
81
82 // No support for fre_mangled_ra_p yet.
83 Info.setReturnAddressSigned(false);
84
85 // sframe_fre_info_word
86 S.emitInt8(Info.getFREInfo());
87
88 // FRE Offsets
89 [[maybe_unused]] unsigned OffsetsEmitted = 1;
90 emitOffset(S, Info.getOffsetSize(), CFAOffset);
91 if (FPOffset) {
92 ++OffsetsEmitted;
93 emitOffset(S, Info.getOffsetSize(), FPOffset);
94 }
95 if (RAOffset) {
96 ++OffsetsEmitted;
97 emitOffset(S, Info.getOffsetSize(), RAOffset);
98 }
99 assert(OffsetsEmitted == RegsTracked &&
100 "Didn't emit the right number of offsets");
101 }
102};
103
104// High-level structure to track info needed to emit a sframe_func_desc_entry
105// and its associated FREs.
106struct SFrameFDE {
107 // Reference to the original dwarf frame to avoid copying.
108 const MCDwarfFrameInfo &DFrame;
109 // Label where this FDE's FREs start.
110 MCSymbol *FREStart;
111 // Frag where this FDE is emitted.
112 MCFragment *Frag;
113 // Unwinding fres
115 // .cfi_remember_state stack
116 SmallVector<SFrameFRE> SaveState;
117
118 SFrameFDE(const MCDwarfFrameInfo &DF, MCSymbol *FRES)
119 : DFrame(DF), FREStart(FRES), Frag(nullptr) {}
120
121 void emit(MCObjectStreamer &S, const MCSymbol *FRESubSectionStart) {
122 MCContext &C = S.getContext();
123
124 // sfde_func_start_address
125 const MCExpr *V = C.getAsmInfo().getExprForFDESymbol(
126 &(*DFrame.Begin), C.getObjectFileInfo()->getFDEEncoding(), S);
127 S.emitValue(V, sizeof(int32_t));
128
129 // sfde_func_size
130 S.emitAbsoluteSymbolDiff(DFrame.End, DFrame.Begin, sizeof(uint32_t));
131
132 // sfde_func_start_fre_off
133 auto *F = S.getCurrentFragment();
134 const MCExpr *Diff = MCBinaryExpr::createSub(
135 MCSymbolRefExpr::create(FREStart, C),
136 MCSymbolRefExpr::create(FRESubSectionStart, C), C);
137
138 F->addFixup(MCFixup::create(F->getContents().size(), Diff,
140 S.emitInt32(0);
141
142 // sfde_func_num_fres
143 S.emitInt32(FREs.size());
144
145 // sfde_func_info word
146
147 // All FREs within an FDE share the same sframe::FREType::AddrX. The value
148 // of 'X' is determined by the FRE with the largest offset, which is the
149 // last. This offset isn't known until relax time, so emit a frag which can
150 // calculate that now.
151 //
152 // At relax time, this FDE frag calculates the proper AddrX value (as well
153 // as the rest of the FDE FuncInfo word). Subsequent FRE frags will read it
154 // from this frag and emit the proper number of bytes.
155 Frag = S.getCurrentFragment();
156 S.emitSFrameCalculateFuncOffset(DFrame.Begin, FREs.back().Label, nullptr,
157 SMLoc());
158
159 // sfde_func_rep_size. Not relevant in non-PCMASK fdes.
160 S.emitInt8(0);
161
162 // sfde_func_padding2
163 S.emitInt16(0);
164 }
165};
166
167// Emitting these field-by-field, instead of constructing the actual structures
168// lets Streamer do target endian-fixups for free.
169
170class SFrameEmitterImpl {
171 MCObjectStreamer &Streamer;
173 uint32_t TotalFREs;
174 ABI SFrameABI;
175 // Target-specific convenience variables to detect when a CFI instruction
176 // references these registers. Unlike in dwarf frame descriptions, they never
177 // escape into the sframe section itself. TODO: These should be retrieved from
178 // the target.
179 unsigned SPReg;
180 unsigned FPReg;
181 unsigned RAReg;
182 int8_t FixedRAOffset;
183 MCSymbol *FDESubSectionStart;
184 MCSymbol *FRESubSectionStart;
185 MCSymbol *FRESubSectionEnd;
186
187 bool setCFARegister(SFrameFRE &FRE, const MCCFIInstruction &I) {
188 if (I.getRegister() == SPReg) {
189 FRE.CFARegSet = true;
190 FRE.Info.setBaseRegister(BaseReg::SP);
191 return true;
192 }
193 if (I.getRegister() == FPReg) {
194 FRE.CFARegSet = true;
195 FRE.Info.setBaseRegister(BaseReg::FP);
196 return true;
197 }
198 Streamer.getContext().reportWarning(
199 I.getLoc(), "canonical Frame Address not in stack- or frame-pointer. "
200 "Omitting SFrame unwind info for this function");
201 return false;
202 }
203
204 bool setCFAOffset(SFrameFRE &FRE, SMLoc Loc, size_t Offset) {
205 if (!FRE.CFARegSet) {
206 Streamer.getContext().reportWarning(
207 Loc, "adjusting CFA offset without a base register. "
208 "Omitting SFrame unwind info for this function");
209 return false;
210 }
211 FRE.CFAOffset = Offset;
212 return true;
213 }
214
215 // Technically, the escape data could be anything, but it is commonly a dwarf
216 // CFI program. Even then, it could contain an arbitrarily complicated Dwarf
217 // expression. Following gnu-gas, look for certain common cases that could
218 // invalidate an FDE, emit a warning for those sequences, and don't generate
219 // an FDE in those cases. Allow any that are known safe. It is likely that
220 // more thorough test cases could refine this code, but it handles the most
221 // important ones compatibly with gas.
222 // Returns true if the CFI escape sequence is safe for sframes.
223 bool isCFIEscapeSafe(SFrameFDE &FDE, const SFrameFRE &FRE,
224 const MCCFIInstruction &CFI) {
225 const MCAsmInfo &AI = Streamer.getContext().getAsmInfo();
226 DWARFDataExtractorSimple data(CFI.getValues(), AI.isLittleEndian(),
227 AI.getCodePointerSize());
228
229 // Normally, both alignment factors are extracted from the enclosing Dwarf
230 // FDE or CIE. We don't have one here. Alignments are used for scaling
231 // factors for ops like CFA_def_cfa_offset_sf. But this particular function
232 // is only interested in registers.
233 dwarf::CFIProgram P(/*CodeAlignmentFactor=*/1,
234 /*DataAlignmentFactor=*/1,
235 Streamer.getContext().getTargetTriple().getArch());
236 uint64_t Offset = 0;
237 if (P.parse(data, &Offset, CFI.getValues().size())) {
238 // Not a parsable dwarf expression. Assume the worst.
239 Streamer.getContext().reportWarning(
240 CFI.getLoc(),
241 "skipping SFrame FDE; .cfi_escape with unknown effects");
242 return false;
243 }
244
245 // This loop deals with dwarf::CFIProgram::Instructions. Everywhere else
246 // this file deals with MCCFIInstructions.
247 for (const dwarf::CFIProgram::Instruction &I : P) {
248 switch (I.Opcode) {
249 case dwarf::DW_CFA_nop:
250 break;
251 case dwarf::DW_CFA_val_offset: {
252 // First argument is a register. Anything that touches CFA, FP, or RA is
253 // a problem, but allow others through. As an even more special case,
254 // allow SP + 0.
255 auto Reg = I.getOperandAsUnsigned(P, 0);
256 // The parser should have failed in this case.
257 assert(Reg && "DW_CFA_val_offset with no register.");
258 bool SPOk = true;
259 if (*Reg == SPReg) {
260 auto Opnd = I.getOperandAsSigned(P, 1);
261 if (!Opnd || *Opnd != 0)
262 SPOk = false;
263 }
264 if (!SPOk || *Reg == RAReg || *Reg == FPReg) {
265 StringRef RN = *Reg == SPReg
266 ? "SP reg "
267 : (*Reg == FPReg ? "FP reg " : "RA reg ");
268 Streamer.getContext().reportWarning(
269 CFI.getLoc(),
270 Twine(
271 "skipping SFrame FDE; .cfi_escape DW_CFA_val_offset with ") +
272 RN + Twine(*Reg));
273 return false;
274 }
275 } break;
276 case dwarf::DW_CFA_expression: {
277 // First argument is a register. Anything that touches CFA, FP, or RA is
278 // a problem, but allow others through.
279 auto Reg = I.getOperandAsUnsigned(P, 0);
280 if (!Reg) {
281 Streamer.getContext().reportWarning(
282 CFI.getLoc(),
283 "skipping SFrame FDE; .cfi_escape with unknown effects");
284 return false;
285 }
286 if (*Reg == SPReg || *Reg == RAReg || *Reg == FPReg) {
287 StringRef RN = *Reg == SPReg
288 ? "SP reg "
289 : (*Reg == FPReg ? "FP reg " : "RA reg ");
290 Streamer.getContext().reportWarning(
291 CFI.getLoc(),
292 Twine(
293 "skipping SFrame FDE; .cfi_escape DW_CFA_expression with ") +
294 RN + Twine(*Reg));
295 return false;
296 }
297 } break;
298 case dwarf::DW_CFA_GNU_args_size: {
299 auto Size = I.getOperandAsSigned(P, 0);
300 // Zero size doesn't affect the cfa.
301 if (Size && *Size == 0)
302 break;
303 if (FRE.Info.getBaseRegister() != BaseReg::FP) {
304 Streamer.getContext().reportWarning(
305 CFI.getLoc(),
306 Twine("skipping SFrame FDE; .cfi_escape DW_CFA_GNU_args_size "
307 "with non frame-pointer CFA"));
308 return false;
309 }
310 } break;
311 // Cases that gas doesn't specially handle. TODO: Some of these could be
312 // analyzed and handled instead of just punting. But these are uncommon,
313 // or should be written as normal cfi directives. Some will need fixes to
314 // the scaling factor.
315 case dwarf::DW_CFA_advance_loc:
316 case dwarf::DW_CFA_offset:
317 case dwarf::DW_CFA_restore:
318 case dwarf::DW_CFA_set_loc:
319 case dwarf::DW_CFA_advance_loc1:
320 case dwarf::DW_CFA_advance_loc2:
321 case dwarf::DW_CFA_advance_loc4:
322 case dwarf::DW_CFA_offset_extended:
323 case dwarf::DW_CFA_restore_extended:
324 case dwarf::DW_CFA_undefined:
325 case dwarf::DW_CFA_same_value:
326 case dwarf::DW_CFA_register:
327 case dwarf::DW_CFA_remember_state:
328 case dwarf::DW_CFA_restore_state:
329 case dwarf::DW_CFA_def_cfa:
330 case dwarf::DW_CFA_def_cfa_register:
331 case dwarf::DW_CFA_def_cfa_offset:
332 case dwarf::DW_CFA_def_cfa_expression:
333 case dwarf::DW_CFA_offset_extended_sf:
334 case dwarf::DW_CFA_def_cfa_sf:
335 case dwarf::DW_CFA_def_cfa_offset_sf:
336 case dwarf::DW_CFA_val_offset_sf:
337 case dwarf::DW_CFA_val_expression:
338 case dwarf::DW_CFA_MIPS_advance_loc8:
339 case dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc:
340 case dwarf::DW_CFA_AARCH64_negate_ra_state:
341 case dwarf::DW_CFA_AARCH64_set_ra_state:
342 case dwarf::DW_CFA_LLVM_def_aspace_cfa:
343 case dwarf::DW_CFA_LLVM_def_aspace_cfa_sf:
344 Streamer.getContext().reportWarning(
345 CFI.getLoc(), "skipping SFrame FDE; .cfi_escape "
346 "CFA expression with unknown side effects");
347 return false;
348 default:
349 // Dwarf expression was only partially valid, and user could have
350 // written anything.
351 Streamer.getContext().reportWarning(
352 CFI.getLoc(),
353 "skipping SFrame FDE; .cfi_escape with unknown effects");
354 return false;
355 }
356 }
357 return true;
358 }
359
360 // Add the effects of CFI to the current FDE, creating a new FRE when
361 // necessary. Return true if the CFI is representable in the sframe format.
362 bool handleCFI(SFrameFDE &FDE, SFrameFRE &FRE, const MCCFIInstruction &CFI) {
363 switch (CFI.getOperation()) {
365 return setCFARegister(FRE, CFI);
368 if (!setCFARegister(FRE, CFI))
369 return false;
370 return setCFAOffset(FRE, CFI.getLoc(), CFI.getOffset());
372 if (CFI.getRegister() == FPReg)
373 FRE.FPOffset = CFI.getOffset();
374 else if (CFI.getRegister() == RAReg)
375 FRE.RAOffset = CFI.getOffset();
376 return true;
378 if (CFI.getRegister() == FPReg)
379 FRE.FPOffset += CFI.getOffset();
380 else if (CFI.getRegister() == RAReg)
381 FRE.RAOffset += CFI.getOffset();
382 return true;
384 return setCFAOffset(FRE, CFI.getLoc(), CFI.getOffset());
386 return setCFAOffset(FRE, CFI.getLoc(), FRE.CFAOffset + CFI.getOffset());
388 if (FDE.FREs.size() == 1) {
389 // Error for gas compatibility: If the initial FRE isn't complete,
390 // then any state is incomplete. FIXME: Dwarf doesn't error here.
391 // Why should sframe?
392 Streamer.getContext().reportWarning(
393 CFI.getLoc(), "skipping SFrame FDE; .cfi_remember_state without "
394 "prior SFrame FRE state");
395 return false;
396 }
397 FDE.SaveState.push_back(FRE);
398 return true;
400 // The first FRE generated has the original state.
401 if (CFI.getRegister() == FPReg)
402 FRE.FPOffset = FDE.FREs.front().FPOffset;
403 else if (CFI.getRegister() == RAReg)
404 FRE.RAOffset = FDE.FREs.front().RAOffset;
405 return true;
407 // The cfi parser will have caught unbalanced directives earlier, so a
408 // mismatch here is an implementation error.
409 assert(!FDE.SaveState.empty() &&
410 "cfi_restore_state without cfi_save_state");
411 FRE = FDE.SaveState.pop_back_val();
412 return true;
414 // This is a string of bytes that contains an arbitrary dwarf-expression
415 // that may or may not affect unwind info.
416 return isCFIEscapeSafe(FDE, FRE, CFI);
417 default:
418 // Instructions that don't affect the CFA, RA, and FP can be safely
419 // ignored.
420 return true;
421 }
422 }
423
424public:
425 SFrameEmitterImpl(MCObjectStreamer &Streamer)
426 : Streamer(Streamer), TotalFREs(0) {
427 assert(Streamer.getContext()
428 .getObjectFileInfo()
429 ->getSFrameABIArch()
430 .has_value());
431 FDEs.reserve(Streamer.getDwarfFrameInfos().size());
432 SFrameABI = *Streamer.getContext().getObjectFileInfo()->getSFrameABIArch();
433 switch (SFrameABI) {
434 case ABI::AArch64EndianBig:
435 case ABI::AArch64EndianLittle:
436 SPReg = 31;
437 RAReg = 29;
438 FPReg = 30;
439 FixedRAOffset = 0;
440 break;
441 case ABI::AMD64EndianLittle:
442 SPReg = 7;
443 // RARegister untracked in this abi. Value chosen to match
444 // MCDwarfFrameInfo constructor.
445 RAReg = static_cast<unsigned>(INT_MAX);
446 FPReg = 6;
447 FixedRAOffset = -8;
448 break;
449 }
450
451 FDESubSectionStart = Streamer.getContext().createTempSymbol();
452 FRESubSectionStart = Streamer.getContext().createTempSymbol();
453 FRESubSectionEnd = Streamer.getContext().createTempSymbol();
454 }
455
456 bool atSameLocation(const MCSymbol *Left, const MCSymbol *Right) {
457 return Left != nullptr && Right != nullptr &&
458 Left->getFragment() == Right->getFragment() &&
459 Left->getOffset() == Right->getOffset();
460 }
461
462 bool equalIgnoringLocation(const SFrameFRE &Left, const SFrameFRE &Right) {
463 return Left.CFAOffset == Right.CFAOffset &&
464 Left.FPOffset == Right.FPOffset && Left.RAOffset == Right.RAOffset &&
465 Left.Info.getFREInfo() == Right.Info.getFREInfo() &&
466 Left.CFARegSet == Right.CFARegSet;
467 }
468
469 void buildSFDE(const MCDwarfFrameInfo &DF) {
470 // Functions with zero size can happen with assembler macros and
471 // machine-generated code. They don't need unwind info at all, so
472 // no need to warn.
473 if (atSameLocation(DF.Begin, DF.End))
474 return;
475 bool Valid = true;
476 SFrameFDE FDE(DF, Streamer.getContext().createTempSymbol());
477 // This would have been set via ".cfi_return_column", but
478 // MCObjectStreamer doesn't emit an MCCFIInstruction for that. It just
479 // sets the DF.RAReg.
480 // FIXME: This also prevents providing a proper location for the error.
481 // LLVM doesn't change the return column itself, so this was
482 // hand-written assembly.
483 if (DF.RAReg != RAReg) {
484 Streamer.getContext().reportWarning(
485 SMLoc(), "non-default RA register in .cfi_return_column " +
486 Twine(DF.RAReg) +
487 ". Omitting SFrame unwind info for this function");
488 Valid = false;
489 }
490 MCSymbol *LastLabel = DF.Begin;
491 SFrameFRE BaseFRE(LastLabel);
492 if (!DF.IsSimple) {
493 for (const auto &CFI :
494 Streamer.getContext().getAsmInfo().getInitialFrameState())
495 if (!handleCFI(FDE, BaseFRE, CFI))
496 Valid = false;
497 }
498 FDE.FREs.push_back(BaseFRE);
499
500 for (const auto &CFI : DF.Instructions) {
501 // Instructions from InitialFrameState may not have a label, but if these
502 // instructions don't, then they are in dead code or otherwise unused.
503 // TODO: This check follows MCDwarf.cpp
504 // FrameEmitterImplementation::emitCFIInstructions, but nothing in the
505 // testsuite triggers it. We should see if it can be removed in both
506 // places, or alternately, add a test to exercise it.
507 auto *L = CFI.getLabel();
508 if (L && !L->isDefined())
509 continue;
510
511 SFrameFRE FRE = FDE.FREs.back();
512 if (!handleCFI(FDE, FRE, CFI))
513 Valid = false;
514
515 // If nothing relevant but the location changed, don't add the FRE.
516 if (equalIgnoringLocation(FRE, FDE.FREs.back()))
517 continue;
518
519 // If the location stayed the same, then update the current
520 // row. Otherwise, add a new one.
521 if (atSameLocation(LastLabel, L))
522 FDE.FREs.back() = FRE;
523 else {
524 FDE.FREs.push_back(FRE);
525 FDE.FREs.back().Label = L;
526 LastLabel = L;
527 }
528 }
529
530 if (Valid) {
531 FDEs.push_back(FDE);
532 TotalFREs += FDE.FREs.size();
533 }
534 }
535
536 void emitPreamble() {
537 Streamer.emitInt16(Magic);
538 Streamer.emitInt8(static_cast<uint8_t>(Version::V2));
539 Streamer.emitInt8(static_cast<uint8_t>(Flags::FDEFuncStartPCRel));
540 }
541
542 void emitHeader() {
543 emitPreamble();
544 // sfh_abi_arch
545 Streamer.emitInt8(static_cast<uint8_t>(SFrameABI));
546 // sfh_cfa_fixed_fp_offset
547 Streamer.emitInt8(0);
548 // sfh_cfa_fixed_ra_offset
549 Streamer.emitInt8(FixedRAOffset);
550 // sfh_auxhdr_len
551 Streamer.emitInt8(0);
552 // shf_num_fdes
553 Streamer.emitInt32(FDEs.size());
554 // shf_num_fres
555 Streamer.emitInt32(TotalFREs);
556
557 // shf_fre_len
558 Streamer.emitAbsoluteSymbolDiff(FRESubSectionEnd, FRESubSectionStart,
559 sizeof(int32_t));
560 // shf_fdeoff. With no sfh_auxhdr, these immediately follow this header.
561 Streamer.emitInt32(0);
562 // shf_freoff
563 Streamer.emitInt32(FDEs.size() *
564 sizeof(sframe::FuncDescEntry<endianness::native>));
565 }
566
567 void emitFDEs() {
568 Streamer.emitLabel(FDESubSectionStart);
569 for (auto &FDE : FDEs) {
570 FDE.emit(Streamer, FRESubSectionStart);
571 }
572 }
573
574 void emitFREs() {
575 Streamer.emitLabel(FRESubSectionStart);
576 for (auto &FDE : FDEs) {
577 Streamer.emitLabel(FDE.FREStart);
578 for (auto &FRE : FDE.FREs)
579 FRE.emit(Streamer, FDE.DFrame.Begin, FDE.Frag);
580 }
581 Streamer.emitLabel(FRESubSectionEnd);
582 }
583};
584
585} // end anonymous namespace
586
588 MCContext &Context = Streamer.getContext();
589 // If this target doesn't support sframes, return now. Gas doesn't warn in
590 // this case, but if we want to, it should be done at option-parsing time,
591 // rather than here.
592 if (!Streamer.getContext()
593 .getObjectFileInfo()
594 ->getSFrameABIArch()
595 .has_value())
596 return;
597
598 SFrameEmitterImpl Emitter(Streamer);
599 ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos();
600
601 // Both the header itself and the FDEs include various offsets and counts.
602 // Therefore, all of this must be precomputed.
603 for (const auto &DFrame : FrameArray)
604 Emitter.buildSFDE(DFrame);
605
606 MCSection *Section = Context.getObjectFileInfo()->getSFrameSection();
607 // Not strictly necessary, but gas always aligns to 8, so match that.
608 Section->ensureMinAlignment(Align(8));
609 Streamer.switchSection(Section);
610 MCSymbol *SectionStart = Context.createTempSymbol();
611 Streamer.emitLabel(SectionStart);
612 Emitter.emitHeader();
613 Emitter.emitFDEs();
614 Emitter.emitFREs();
615}
616
619 MCFragment *FDEFrag) {
620 // If encoding into the FDE Frag itself, generate the sfde_func_info.
621 if (FDEFrag == nullptr) {
622 // sfde_func_info
623
624 // Offset is the difference between the function start label and the final
625 // FRE's offset, which is the max offset for this FDE.
627 I.Info = 0;
628 if (isUInt<8>(Offset))
629 I.setFREType(FREType::Addr1);
630 else if (isUInt<16>(Offset))
631 I.setFREType(FREType::Addr2);
632 else {
634 I.setFREType(FREType::Addr4);
635 }
636 I.setFDEType(FDEType::PCInc);
637 // TODO: When we support pauth keys, this will need to be retrieved
638 // from the frag itself.
639 I.setPAuthKey(0);
640
641 Out.push_back(I.getFuncInfo());
642 return;
643 }
644
645 const auto &FDEData = FDEFrag->getVarContents();
647 I.Info = FDEData.back();
648 FREType T = I.getFREType();
649 llvm::endianness E = C.getAsmInfo().isLittleEndian()
652 // sfre_start_address
653 switch (T) {
654 case FREType::Addr1:
655 assert(isUInt<8>(Offset) && "Miscalculated Sframe FREType");
657 break;
658 case FREType::Addr2:
659 assert(isUInt<16>(Offset) && "Miscalculated Sframe FREType");
661 break;
662 case FREType::Addr4:
663 assert(isUInt<32>(Offset) && "Miscalculated Sframe FREType");
665 break;
666 }
667}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
dxil DXContainer Global Emitter
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
#define T
#define P(N)
This file contains data-structure definitions and constants to support unwinding based on ....
static Split data
std::unique_ptr< MCStreamer > && Streamer
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
bool isLittleEndian() const
True if the target is little endian.
Definition MCAsmInfo.h:463
unsigned getCodePointerSize() const
Get the code pointer size in bytes.
Definition MCAsmInfo.h:454
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
MCSymbol * getLabel() const
Definition MCDwarf.h:834
unsigned getRegister() const
Definition MCDwarf.h:836
SMLoc getLoc() const
Definition MCDwarf.h:893
OpType getOperation() const
Definition MCDwarf.h:833
StringRef getValues() const
Definition MCDwarf.h:883
int64_t getOffset() const
Definition MCDwarf.h:855
Context object for machine code objects.
Definition MCContext.h:83
static MCFixupKind getDataKindForSize(unsigned Size)
Return the generic fixup kind for a value with the given size.
Definition MCFixup.h:110
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Definition MCFixup.h:86
MutableArrayRef< char > getVarContents()
Definition MCSection.h:707
Streaming object file generation interface.
void emitSFrameCalculateFuncOffset(const MCSymbol *FunCabsel, const MCSymbol *FREBegin, MCFragment *FDEFrag, SMLoc Loc)
void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) override
Emit the absolute difference between two symbols if possible.
static LLVM_ABI void emit(MCObjectStreamer &Streamer)
Definition MCSFrame.cpp:587
static LLVM_ABI void encodeFuncOffset(MCContext &C, uint64_t Offset, SmallVectorImpl< char > &Out, MCFragment *FDEFrag)
Definition MCSFrame.cpp:617
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition MCSection.h:580
MCFragment * getCurrentFragment() const
Definition MCStreamer.h:449
MCContext & getContext() const
Definition MCStreamer.h:326
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
void emitInt16(uint64_t Value)
Definition MCStreamer.h:768
void emitInt32(uint64_t Value)
Definition MCStreamer.h:769
void emitInt8(uint64_t Value)
Definition MCStreamer.h:767
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
@ Valid
The data is already valid.
FREOffset
Size of stack offsets. Bits 6-7 of FREInfo.Info.
Definition SFrame.h:71
constexpr uint16_t Magic
Definition SFrame.h:32
FREType
SFrame FRE Types. Bits 0-3 of FuncDescEntry.Info.
Definition SFrame.h:52
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition Endian.h:82
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
endianness
Definition bit.h:71
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
BaseReg getBaseRegister() const
Definition SFrame.h:141
void setBaseRegister(BaseReg Reg)
Definition SFrame.h:152