blob: 447f22eaaf17eb55be59f5355c4c1edac584913d [file] [log] [blame] [edit]
//===- 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();
}