AArch64ELFStreamer.cpp [plain text]
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELF.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCELFSymbolFlags.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
class AArch64ELFStreamer : public MCELFStreamer {
public:
AArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
MCCodeEmitter *Emitter)
: MCELFStreamer(Context, TAB, OS, Emitter), MappingSymbolCounter(0),
LastEMS(EMS_None) {}
~AArch64ELFStreamer() {}
virtual void ChangeSection(const MCSection *Section,
const MCExpr *Subsection) {
LastMappingSymbols[getPreviousSection().first] = LastEMS;
LastEMS = LastMappingSymbols.lookup(Section);
MCELFStreamer::ChangeSection(Section, Subsection);
}
virtual void EmitInstruction(const MCInst& Inst) {
EmitA64MappingSymbol();
MCELFStreamer::EmitInstruction(Inst);
}
virtual void EmitBytes(StringRef Data) {
EmitDataMappingSymbol();
MCELFStreamer::EmitBytes(Data);
}
virtual void EmitValueImpl(const MCExpr *Value, unsigned Size,
const SMLoc &Loc) {
EmitDataMappingSymbol();
MCELFStreamer::EmitValueImpl(Value, Size, Loc);
}
private:
enum ElfMappingSymbol {
EMS_None,
EMS_A64,
EMS_Data
};
void EmitDataMappingSymbol() {
if (LastEMS == EMS_Data) return;
EmitMappingSymbol("$d");
LastEMS = EMS_Data;
}
void EmitA64MappingSymbol() {
if (LastEMS == EMS_A64) return;
EmitMappingSymbol("$x");
LastEMS = EMS_A64;
}
void EmitMappingSymbol(StringRef Name) {
MCSymbol *Start = getContext().CreateTempSymbol();
EmitLabel(Start);
MCSymbol *Symbol =
getContext().GetOrCreateSymbol(Name + "." +
Twine(MappingSymbolCounter++));
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
MCELF::SetType(SD, ELF::STT_NOTYPE);
MCELF::SetBinding(SD, ELF::STB_LOCAL);
SD.setExternal(false);
AssignSection(Symbol, getCurrentSection().first);
const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext());
Symbol->setVariableValue(Value);
}
int64_t MappingSymbolCounter;
DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;
ElfMappingSymbol LastEMS;
};
}
namespace llvm {
MCELFStreamer* createAArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter,
bool RelaxAll, bool NoExecStack) {
AArch64ELFStreamer *S = new AArch64ELFStreamer(Context, TAB, OS, Emitter);
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
if (NoExecStack)
S->getAssembler().setNoExecStack(true);
return S;
}
}