diff options
Diffstat (limited to 'lib/MC/MCMachOStreamer.cpp')
-rw-r--r-- | lib/MC/MCMachOStreamer.cpp | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 99a819f..a7a8a5d 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -137,6 +137,8 @@ public: virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, unsigned MaxBytesToEmit = 0); + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value = 0); @@ -333,7 +335,22 @@ void MCMachOStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size, unsigned AddrSpace) { - new MCFillFragment(*AddValueSymbols(Value), Size, 1, CurSectionData); + MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); + if (!DF) + DF = new MCDataFragment(CurSectionData); + + // Avoid fixups when possible. + int64_t AbsValue; + if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue)) { + // FIXME: Endianness assumption. + for (unsigned i = 0; i != Size; ++i) + DF->getContents().push_back(uint8_t(AbsValue >> (i * 8))); + } else { + DF->getFixups().push_back(MCAsmFixup(DF->getContents().size(), + *AddValueSymbols(Value), + MCFixup::getKindForSize(Size))); + DF->getContents().resize(DF->getContents().size() + Size, 0); + } } void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, @@ -342,7 +359,20 @@ void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, if (MaxBytesToEmit == 0) MaxBytesToEmit = ByteAlignment; new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, - CurSectionData); + false /* EmitNops */, CurSectionData); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > CurSectionData->getAlignment()) + CurSectionData->setAlignment(ByteAlignment); +} + +void MCMachOStreamer::EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) { + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + // FIXME the 0x90 is the default x86 1 byte nop opcode. + new MCAlignFragment(ByteAlignment, 0x90, 1, MaxBytesToEmit, + true /* EmitNops */, CurSectionData); // Update the maximum alignment on the current section if necessary. if (ByteAlignment > CurSectionData->getAlignment()) @@ -365,12 +395,23 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { CurSectionData->setHasInstructions(true); - // FIXME: Relocations! SmallVector<MCFixup, 4> Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); Emitter->EncodeInstruction(Inst, VecOS, Fixups); - EmitBytes(VecOS.str(), 0); + VecOS.flush(); + + // Add the fixups and data. + MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); + if (!DF) + DF = new MCDataFragment(CurSectionData); + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + MCFixup &F = Fixups[i]; + DF->getFixups().push_back(MCAsmFixup(DF->getContents().size()+F.getOffset(), + *F.getValue(), + F.getKind())); + } + DF->getContents().append(Code.begin(), Code.end()); } void MCMachOStreamer::Finish() { |