| //===- lib/MC/MCSFrame.cpp - MCSFrame implementation ----------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/MC/MCSFrame.h" |
| #include "llvm/BinaryFormat/SFrame.h" |
| #include "llvm/MC/MCContext.h" |
| #include "llvm/MC/MCObjectFileInfo.h" |
| #include "llvm/MC/MCObjectStreamer.h" |
| #include "llvm/MC/MCSection.h" |
| #include "llvm/MC/MCSymbol.h" |
| #include "llvm/Support/EndianStream.h" |
| |
| using namespace llvm; |
| using namespace sframe; |
| |
| namespace { |
| |
| // Emitting these field-by-field, instead of constructing the actual structures |
| // lets Streamer do target endian-fixups for free. |
| |
| class SFrameEmitterImpl { |
| MCObjectStreamer &Streamer; |
| ABI SFrameABI; |
| MCSymbol *FDESubSectionStart; |
| MCSymbol *FRESubSectionStart; |
| MCSymbol *FRESubSectionEnd; |
| |
| public: |
| SFrameEmitterImpl(MCObjectStreamer &Streamer) : Streamer(Streamer) { |
| assert(Streamer.getContext() |
| .getObjectFileInfo() |
| ->getSFrameABIArch() |
| .has_value()); |
| SFrameABI = *Streamer.getContext().getObjectFileInfo()->getSFrameABIArch(); |
| FDESubSectionStart = Streamer.getContext().createTempSymbol(); |
| FRESubSectionStart = Streamer.getContext().createTempSymbol(); |
| FRESubSectionEnd = Streamer.getContext().createTempSymbol(); |
| } |
| |
| void emitPreamble() { |
| Streamer.emitInt16(Magic); |
| Streamer.emitInt8(static_cast<uint8_t>(Version::V2)); |
| Streamer.emitInt8(0); |
| } |
| |
| void emitHeader() { |
| emitPreamble(); |
| // sfh_abi_arch |
| Streamer.emitInt8(static_cast<uint8_t>(SFrameABI)); |
| // sfh_cfa_fixed_fp_offset |
| Streamer.emitInt8(0); |
| // sfh_cfa_fixed_ra_offset |
| Streamer.emitInt8(0); |
| // sfh_auxhdr_len |
| Streamer.emitInt8(0); |
| // shf_num_fdes |
| Streamer.emitInt32(0); |
| // shf_num_fres |
| Streamer.emitInt32(0); |
| // shf_fre_len |
| Streamer.emitAbsoluteSymbolDiff(FRESubSectionEnd, FRESubSectionStart, |
| sizeof(int32_t)); |
| // shf_fdeoff. With no sfh_auxhdr, these immediately follow this header. |
| Streamer.emitInt32(0); |
| // shf_freoff |
| Streamer.emitAbsoluteSymbolDiff(FRESubSectionStart, FDESubSectionStart, |
| sizeof(uint32_t)); |
| } |
| |
| void emitFDEs() { Streamer.emitLabel(FDESubSectionStart); } |
| |
| void emitFREs() { |
| Streamer.emitLabel(FRESubSectionStart); |
| Streamer.emitLabel(FRESubSectionEnd); |
| } |
| }; |
| |
| } // end anonymous namespace |
| |
| void MCSFrameEmitter::emit(MCObjectStreamer &Streamer) { |
| MCContext &Context = Streamer.getContext(); |
| SFrameEmitterImpl Emitter(Streamer); |
| |
| MCSection *Section = Context.getObjectFileInfo()->getSFrameSection(); |
| // Not strictly necessary, but gas always aligns to 8, so match that. |
| Section->ensureMinAlignment(Align(8)); |
| Streamer.switchSection(Section); |
| MCSymbol *SectionStart = Context.createTempSymbol(); |
| Streamer.emitLabel(SectionStart); |
| Emitter.emitHeader(); |
| Emitter.emitFDEs(); |
| Emitter.emitFREs(); |
| } |