#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCValue.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
private:
MCAssembler Assembler;
-
MCCodeEmitter *Emitter;
-
MCSectionData *CurSectionData;
- DenseMap<const MCSection*, MCSectionData*> SectionMap;
-
- DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap;
-
private:
MCFragment *getCurrentFragment() const {
assert(CurSectionData && "No current section!");
return 0;
}
- MCSectionData &getSectionData(const MCSection &Section) {
- MCSectionData *&Entry = SectionMap[&Section];
-
- if (!Entry)
- Entry = new MCSectionData(Section, &Assembler);
-
- return *Entry;
- }
-
- MCSymbolData &getSymbolData(const MCSymbol &Symbol) {
- MCSymbolData *&Entry = SymbolMap[&Symbol];
-
- if (!Entry)
- Entry = new MCSymbolData(Symbol, 0, 0, &Assembler);
-
- return *Entry;
- }
-
public:
MCMachOStreamer(MCContext &Context, raw_ostream &_OS, MCCodeEmitter *_Emitter)
: MCStreamer(Context), Assembler(Context, _OS), Emitter(_Emitter),
const MCExpr *AddValueSymbols(const MCExpr *Value) {
switch (Value->getKind()) {
+ case MCExpr::Target: assert(0 && "Can't handle target exprs yet!");
case MCExpr::Constant:
break;
}
case MCExpr::SymbolRef:
- getSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
+ Assembler.getOrCreateSymbolData(
+ cast<MCSymbolRefExpr>(Value)->getSymbol());
break;
case MCExpr::Unary:
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment);
+ virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
+ assert(0 && "macho doesn't support this directive");
+ }
virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
assert(0 && "macho doesn't support this directive");
}
unsigned Size = 0, unsigned ByteAlignment = 0);
virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace);
+ virtual void EmitGPRel32Value(const MCExpr *Value) {
+ assert(0 && "macho doesn't support this directive");
+ }
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);
+
+ virtual void EmitFileDirective(StringRef Filename) {
+ errs() << "FIXME: MCMachoStreamer:EmitFileDirective not implemented\n";
+ }
+ virtual void EmitDwarfFileDirective(unsigned FileNo, StringRef Filename) {
+ errs() << "FIXME: MCMachoStreamer:EmitDwarfFileDirective not implemented\n";
+ }
+
virtual void EmitInstruction(const MCInst &Inst);
virtual void Finish();
if (Section == CurSection) return;
CurSection = Section;
- CurSectionData = &getSectionData(*Section);
+ CurSectionData = &Assembler.getOrCreateSectionData(*Section);
}
void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
if (!F)
F = new MCDataFragment(CurSectionData);
- MCSymbolData &SD = getSymbolData(*Symbol);
+ MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol);
assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
SD.setFragment(F);
SD.setOffset(F->getContents().size());
}
// Adding a symbol attribute always introduces the symbol, note that an
- // important side effect of calling getSymbolData here is to register the
- // symbol with the assembler.
- MCSymbolData &SD = getSymbolData(*Symbol);
+ // important side effect of calling getOrCreateSymbolData here is to register
+ // the symbol with the assembler.
+ MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol);
// The implementation of symbol attributes is designed to match 'as', but it
// leaves much to desired. It doesn't really make sense to arbitrarily add and
// defined.
switch (Attribute) {
case MCSA_Invalid:
+ case MCSA_ELF_TypeFunction:
+ case MCSA_ELF_TypeIndFunction:
+ case MCSA_ELF_TypeObject:
+ case MCSA_ELF_TypeTLS:
+ case MCSA_ELF_TypeCommon:
+ case MCSA_ELF_TypeNoType:
case MCSA_IndirectSymbol:
case MCSA_Hidden:
case MCSA_Internal:
// Encode the 'desc' value into the lowest implementation defined bits.
assert(DescValue == (DescValue & SF_DescFlagsMask) &&
"Invalid .desc value!");
- getSymbolData(*Symbol).setFlags(DescValue & SF_DescFlagsMask);
+ Assembler.getOrCreateSymbolData(*Symbol).setFlags(DescValue&SF_DescFlagsMask);
}
void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
// FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
- MCSymbolData &SD = getSymbolData(*Symbol);
+ MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol);
SD.setExternal(true);
SD.setCommon(Size, ByteAlignment);
}
void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
unsigned Size, unsigned ByteAlignment) {
- MCSectionData &SectData = getSectionData(*Section);
+ MCSectionData &SectData = Assembler.getOrCreateSectionData(*Section);
// The symbol may not be present, which only creates the section.
if (!Symbol)
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
- MCSymbolData &SD = getSymbolData(*Symbol);
+ MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol);
MCFragment *F = new MCZeroFillFragment(Size, ByteAlignment, &SectData);
SD.setFragment(F);
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,
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())
if (!Emitter)
llvm_unreachable("no code emitter available!");
- // FIXME: Emitting an instruction should cause S_ATTR_SOME_INSTRUCTIONS to
- // be set for the current section.
- // FIXME: Relocations!
+ CurSectionData->setHasInstructions(true);
+
+ SmallVector<MCFixup, 4> Fixups;
SmallString<256> Code;
raw_svector_ostream VecOS(Code);
- Emitter->EncodeInstruction(Inst, VecOS);
- EmitBytes(VecOS.str(), 0);
+ Emitter->EncodeInstruction(Inst, VecOS, Fixups);
+ 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() {