LLVM 22.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_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()
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!")
dxil DXContainer Global Emitter
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
Register Reg
#define T
#define P(N)
This file contains data-structure definitions and constants to support unwinding based on ....
static Split data
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
bool isLittleEndian() const
True if the target is little endian.
Definition MCAsmInfo.h:452
unsigned getCodePointerSize() const
Get the code pointer size in bytes.
Definition MCAsmInfo.h:443
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:428
MCSymbol * getLabel() const
Definition MCDwarf.h:721
unsigned getRegister() const
Definition MCDwarf.h:723
SMLoc getLoc() const
Definition MCDwarf.h:766
OpType getOperation() const
Definition MCDwarf.h:720
StringRef getValues() const
Definition MCDwarf.h:760
int64_t getOffset() const
Definition MCDwarf.h:745
Context object for machine code objects.
Definition MCContext.h:83
const MCObjectFileInfo * getObjectFileInfo() const
Definition MCContext.h:416
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:647
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 void emit(MCObjectStreamer &Streamer)
Definition MCSFrame.cpp:587
static 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:521
MCFragment * getCurrentFragment() const
Definition MCStreamer.h:432
MCContext & getContext() const
Definition MCStreamer.h:314
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
void emitInt16(uint64_t Value)
Definition MCStreamer.h:749
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:750
void emitInt8(uint64_t Value)
Definition MCStreamer.h:748
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
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
size - Get the string size.
Definition StringRef.h:146
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ FRE
Reciprocal estimate instructions (unary FP ops).
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:477
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:189
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