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