MCCodeEmitter *Emitter_)
: MCStreamer(Context),
Assembler(new MCAssembler(Context, TAB, *Emitter_,
- *TAB.createObjectWriter(OS), OS)),
+ *TAB.createObjectWriter(OS))),
EmitEHFrame(true), EmitDebugFrame(false) {}
MCObjectStreamer::~MCObjectStreamer() {
}
void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
- if (PendingLabels.size()) {
- if (!F) {
- F = new MCDataFragment();
- MCSection *CurSection = getCurrentSectionOnly();
- CurSection->getFragmentList().insert(CurInsertionPoint, F);
- F->setParent(CurSection);
- }
- for (MCSymbol *Sym : PendingLabels) {
- Sym->setFragment(F);
- Sym->setOffset(FOffset);
- }
- PendingLabels.clear();
+ if (PendingLabels.empty())
+ return;
+ if (!F) {
+ F = new MCDataFragment();
+ MCSection *CurSection = getCurrentSectionOnly();
+ CurSection->getFragmentList().insert(CurInsertionPoint, F);
+ F->setParent(CurSection);
+ }
+ for (MCSymbol *Sym : PendingLabels) {
+ Sym->setFragment(F);
+ Sym->setOffset(FOffset);
}
+ PendingLabels.clear();
}
-bool MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
+void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
const MCSymbol *Lo,
unsigned Size) {
- // Must both be assigned to the same (valid) fragment.
- if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment())
- return false;
-
- // Must be a data fragment.
- if (!isa<MCDataFragment>(Hi->getFragment()))
- return false;
+ // If not assigned to the same (valid) fragment, fallback.
+ if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
+ Hi->isVariable() || Lo->isVariable()) {
+ MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
+ return;
+ }
assert(Hi->getOffset() >= Lo->getOffset() &&
"Expected Hi to be greater than Lo");
EmitIntValue(Hi->getOffset() - Lo->getOffset(), Size);
- return true;
}
void MCObjectStreamer::reset() {
}
void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
- const SMLoc &Loc) {
+ SMLoc Loc) {
MCStreamer::EmitValueImpl(Value, Size, Loc);
MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
MCLineEntry::Make(this, getCurrentSection().first);
MCStreamer::EmitLabel(Symbol);
getAssembler().registerSymbol(*Symbol);
- assert(!Symbol->getFragment() && "Unexpected fragment on symbol data!");
// If there is a current fragment, mark the symbol as pointing into it.
// Otherwise queue the label and set its fragment pointer when we emit the
raw_svector_ostream VecOS(Code);
getAssembler().getEmitter().encodeInstruction(Inst, VecOS, IF->getFixups(),
STI);
- VecOS.flush();
IF->getContents().append(Code.begin(), Code.end());
}
return AddrDelta;
}
-static void emitDwarfSetLineAddr(MCObjectStreamer &OS, int64_t LineDelta,
- const MCSymbol *Label, int PointerSize) {
+static void emitDwarfSetLineAddr(MCObjectStreamer &OS,
+ MCDwarfLineTableParams Params,
+ int64_t LineDelta, const MCSymbol *Label,
+ int PointerSize) {
// emit the sequence to set the address
OS.EmitIntValue(dwarf::DW_LNS_extended_op, 1);
OS.EmitULEB128IntValue(PointerSize + 1);
OS.EmitSymbolValue(Label, PointerSize);
// emit the sequence for the LineDelta (from 1) and a zero address delta.
- MCDwarfLineAddr::Emit(&OS, LineDelta, 0);
+ MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
}
void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
const MCSymbol *Label,
unsigned PointerSize) {
if (!LastLabel) {
- emitDwarfSetLineAddr(*this, LineDelta, Label, PointerSize);
+ emitDwarfSetLineAddr(*this, Assembler->getDWARFLinetableParams(), LineDelta,
+ Label, PointerSize);
return;
}
const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
int64_t Res;
if (AddrDelta->evaluateAsAbsolute(Res, getAssembler())) {
- MCDwarfLineAddr::Emit(this, LineDelta, Res);
+ MCDwarfLineAddr::Emit(this, Assembler->getDWARFLinetableParams(), LineDelta,
+ Res);
return;
}
insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta));
void MCObjectStreamer::EmitBytes(StringRef Data) {
MCLineEntry::Make(this, getCurrentSection().first);
- getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end());
+ MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
+ DF->getContents().append(Data.begin(), Data.end());
}
void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
// Associate GPRel32 fixup with data and resize data area
void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
Value, FK_GPRel_4));
// Associate GPRel32 fixup with data and resize data area
void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
Value, FK_GPRel_4));
void MCObjectStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) {
// FIXME: A MCFillFragment would be more memory efficient but MCExpr has
// problems evaluating expressions across multiple fragments.
- getOrCreateDataFragment()->getContents().append(NumBytes, FillValue);
+ MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
+ DF->getContents().append(NumBytes, FillValue);
}
void MCObjectStreamer::EmitZeros(uint64_t NumBytes) {
MCGenDwarfInfo::Emit(this);
// Dump out the dwarf file & directory tables and line tables.
- MCDwarfLineTable::Emit(this);
+ MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams());
flushPendingLabels(nullptr);
getAssembler().Finish();