For Target specific directives, the MCStreamer
has a MCTargetStreamer
instance.
// Inheritance relations
// MCTargetStreamer for directives.
// llvm/include/llvm/MCStreamer.h
MCTargetStreamer (contain an instance `MCStreamer` as member `Streamer`)
-> ARMTargetStreamer // include/llvm/MCStreamer.h
-> MipsTargetStreamer // lib/Target/Mips/MipsTargetStreamer.h
-> MipsTargetAsmStreamer // lib/Target/Mips/MipsTargetStreamer.h
-> MipsTargetELFStreamer // lib/Target/Mips/MipsTargetStreamer.h
-> RISCVTargetStreamer // lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
Source code list:
lib/Target/Mips/MipsTargetStreamer.h
MipsTargetStreamer
classMipsTargetAsmStreamer
class, for ascii asm output
MCStreamer &Streamer;
.MipsTargetELFStreamer
class, for ELF object output
MCStreamer &Streamer;
.lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
MipsTargetELFStreamer::finish()
function. Final step???lib/Target/Mips/MipsTargetObjectFile.h
lib/Target/Mips/MipsTargetObjectFile.cpp
Constructor:
MipsTargetStreamer(MCStreamer &S, llvm::Optional<unsigned> CheriCapSize);
emitStoreWithImmOffset/SCwithSymOffset()
emitLoadWithImmOffset()
emitGPRestore()
Constructor:
MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
Global/Section/LD/ST related functions:
emitDirectiveCpLoad/CpLocal/CpRestore/Cpsetup/Cpreturn()
emitLabel(MCSymbol *Symbol)
emitAssignment(MCSymbol *Symbol, const MCExpr *Value)
emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg)
finish()
:
// lib/Target/MipsMCTargetDesc/MipsTargetStreamer.cpp
finish()
-> MCObjectFileInfo.get_x_Section() // .text, .data, .bss
-> MCAssembler.registerSection(_x_) // TextSection, DataSection, BSSSection
-> MCAssembler.setELFHeaderEFlags(..) // ELF_MIPS_ABI_CHERIABI
-> MipsELFStreamer.EmitMipsOptionRecords(); // `.Mips.options` section: Streamer->EmitIntValue()....
-> emitMipsAbiFlags(); //?
finish()
is called in MCStreamer::Finish()
in lib/MC/MCStreamer.cpp
Finish() -> FinishImpl(), both of them finally call a set of functions as
-> EmitValue() -> EmitZeros() -> finish() -> FinishImpl() is empty.
void MCStreamer::Finish() {
if ((!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End) ||
(!WinFrameInfos.empty() && !WinFrameInfos.back()->End)) {
getContext().reportError(SMLoc(), "Unfinished frame!");
return;
}
if (!FatRelocs.empty()) {
MCSection *DefaultRelocSection = Context.getELFSection("__cap_relocs",
ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
DefaultRelocSection->setAlignment(llvm::Align(8));
for (auto &R : FatRelocs) {
MCSymbol *Sym;
const MCExpr *Value;
MCSection *RelocSection;
StringRef GroupName;
std::tie(Sym, Value, GroupName) = R;
if (GroupName != StringRef()) {
RelocSection =
Context.getELFSection("__cap_relocs", ELF::SHT_PROGBITS,
ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, GroupName);
RelocSection->setAlignment(llvm::Align(8));
} else {
RelocSection = DefaultRelocSection;
}
SwitchSection(RelocSection);
EmitValue(MCSymbolRefExpr::create(Sym, Context), 8);
if (const MCSymbolRefExpr *Sym = dyn_cast<MCSymbolRefExpr>(Value)) {
EmitValue(Sym, 8);
EmitZeros(8);
} else {
const MCBinaryExpr *Bin = cast<MCBinaryExpr>(Value);
EmitValue(cast<MCSymbolRefExpr>(Bin->getLHS()), 8);
EmitValue(Bin->getRHS(), 8);
}
// TODO: Emit size / perms here.
EmitZeros(16);
}
}
MCTargetStreamer *TS = getTargetStreamer();
if (TS)
TS->finish();
FinishImpl();
}
//
void MipsRegInfoRecord::EmitMipsOptionRecord() {
MCAssembler &MCA = Streamer->getAssembler();
MipsTargetStreamer *MTS =
static_cast<MipsTargetStreamer *>(Streamer->getTargetStreamer());
Streamer->PushSection();
// We need to distinguish between N64 and the rest because at the moment
// we don't emit .Mips.options for other ELFs other than N64.
// Since .reginfo has the same information as .Mips.options (ODK_REGINFO),
// we can use the same abstraction (MipsRegInfoRecord class) to handle both.
if (MTS->getABI().IsN64()) {
// The EntrySize value of 1 seems strange since the records are neither
// 1-byte long nor fixed length but it matches the value GAS emits.
MCSectionELF *Sec =
Context.getELFSection(".MIPS.options", ELF::SHT_MIPS_OPTIONS,
ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, 1, "");
MCA.registerSection(*Sec);
Sec->setAlignment(llvm::Align(8));
Streamer->SwitchSection(Sec);
Streamer->EmitIntValue(ELF::ODK_REGINFO, 1); // kind
Streamer->EmitIntValue(40, 1); // size
Streamer->EmitIntValue(0, 2); // section
Streamer->EmitIntValue(0, 4); // info
Streamer->EmitIntValue(ri_gprmask, 4);
Streamer->EmitIntValue(0, 4); // pad
Streamer->EmitIntValue(ri_cprmask[0], 4);
Streamer->EmitIntValue(ri_cprmask[1], 4);
Streamer->EmitIntValue(ri_cprmask[2], 4);
Streamer->EmitIntValue(ri_cprmask[3], 4);
Streamer->EmitIntValue(ri_gp_value, 8);
} else {
MCSectionELF *Sec = Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO,
ELF::SHF_ALLOC, 24, "");
MCA.registerSection(*Sec);
Sec->setAlignment(MTS->getABI().IsN32() ? llvm::Align(8) : llvm::Align(4));
Streamer->SwitchSection(Sec);
Streamer->EmitIntValue(ri_gprmask, 4);
Streamer->EmitIntValue(ri_cprmask[0], 4);
Streamer->EmitIntValue(ri_cprmask[1], 4);
Streamer->EmitIntValue(ri_cprmask[2], 4);
Streamer->EmitIntValue(ri_cprmask[3], 4);
assert((ri_gp_value & 0xffffffff) == ri_gp_value);
Streamer->EmitIntValue(ri_gp_value, 4);
}
Streamer->PopSection();
}
MipsELFStreamer Streamer
, defined in lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h
EmitIntValue()
is defined as:
// lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp
void MipsELFStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
MCELFStreamer::EmitIntValue(Value, Size);
Labels.clear();
}
See more at MCStreamer - MipsELFSteamer::EmitIntValue
If you could revise
the fundmental principles of
computer system design
to improve security...
... what would you change?