#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCExpr.h"
#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;
return 0;
}
- MCSymbolData &getSymbolData(MCSymbol &Symbol) {
+ 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)
public:
MCMachOStreamer(MCContext &Context, raw_ostream &_OS, MCCodeEmitter *_Emitter)
- : MCStreamer(Context), Assembler(_OS), Emitter(_Emitter),
+ : MCStreamer(Context), Assembler(Context, _OS), Emitter(_Emitter),
CurSectionData(0) {}
~MCMachOStreamer() {}
- const MCValue &AddValueSymbols(const MCValue &Value) {
- if (Value.getSymA())
- getSymbolData(*const_cast<MCSymbol*>(Value.getSymA()));
- if (Value.getSymB())
- getSymbolData(*const_cast<MCSymbol*>(Value.getSymB()));
+ const MCExpr *AddValueSymbols(const MCExpr *Value) {
+ switch (Value->getKind()) {
+ case MCExpr::Constant:
+ break;
+
+ case MCExpr::Binary: {
+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
+ AddValueSymbols(BE->getLHS());
+ AddValueSymbols(BE->getRHS());
+ break;
+ }
+
+ case MCExpr::SymbolRef:
+ getSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
+ break;
+
+ case MCExpr::Unary:
+ AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr());
+ break;
+ }
+
return Value;
}
virtual void EmitAssemblerFlag(AssemblerFlag Flag);
- virtual void EmitAssignment(MCSymbol *Symbol, const MCValue &Value,
- bool MakeAbsolute = false);
+ virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute);
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
- virtual void EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value);
-
virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
- unsigned Pow2Alignment, bool IsLocal);
+ unsigned ByteAlignment);
- virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = NULL,
- unsigned Size = 0, unsigned Pow2Alignment = 0);
+ virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
+ unsigned Size = 0, unsigned ByteAlignment = 0);
- virtual void EmitBytes(const StringRef &Data);
+ virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
- virtual void EmitValue(const MCValue &Value, unsigned Size);
+ virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace);
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0);
- virtual void EmitValueToOffset(const MCValue &Offset,
+ virtual void EmitValueToOffset(const MCExpr *Offset,
unsigned char Value = 0);
virtual void EmitInstruction(const MCInst &Inst);
// If already in this section, then this is a noop.
if (Section == CurSection) return;
-
- CurSection = Section;
- MCSectionData *&Entry = SectionMap[Section];
-
- if (!Entry)
- Entry = new MCSectionData(*Section, &Assembler);
- CurSectionData = Entry;
+ CurSection = Section;
+ CurSectionData = &getSectionData(*Section);
}
void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
switch (Flag) {
- default:
- llvm_unreachable("FIXME: Not yet implemented!");
-
case SubsectionsViaSymbols:
Assembler.setSubsectionsViaSymbols(true);
- break;
+ return;
}
+
+ assert(0 && "invalid assembler flag!");
}
-void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol,
- const MCValue &Value,
- bool MakeAbsolute) {
+void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
// Only absolute symbols can be redefined.
assert((Symbol->isUndefined() || Symbol->isAbsolute()) &&
"Cannot define a symbol twice!");
- llvm_unreachable("FIXME: Not yet implemented!");
+ // FIXME: Lift context changes into super class.
+ // FIXME: Set associated section.
+ Symbol->setValue(Value);
}
void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
break;
case MCStreamer::Global:
- getSymbolData(*Symbol).setExternal(true);
+ SD.setExternal(true);
break;
case MCStreamer::LazyReference:
getSymbolData(*Symbol).setFlags(DescValue & SF_DescFlagsMask);
}
-void MCMachOStreamer::EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value) {
- llvm_unreachable("FIXME: Not yet implemented!");
-}
-
void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
- unsigned Pow2Alignment,
- bool IsLocal) {
- llvm_unreachable("FIXME: Not yet implemented!");
+ unsigned ByteAlignment) {
+ // 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);
+ SD.setExternal(true);
+ SD.setCommon(Size, ByteAlignment);
}
-void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- unsigned Size, unsigned Pow2Alignment) {
- llvm_unreachable("FIXME: Not yet implemented!");
+void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
+ unsigned Size, unsigned ByteAlignment) {
+ MCSectionData &SectData = getSectionData(*Section);
+
+ // The symbol may not be present, which only creates the section.
+ if (!Symbol)
+ return;
+
+ // FIXME: Assert that this section has the zerofill type.
+
+ assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
+
+ MCSymbolData &SD = getSymbolData(*Symbol);
+
+ MCFragment *F = new MCZeroFillFragment(Size, ByteAlignment, &SectData);
+ SD.setFragment(F);
+
+ Symbol->setSection(*Section);
+
+ // Update the maximum alignment on the zero fill section if necessary.
+ if (ByteAlignment > SectData.getAlignment())
+ SectData.setAlignment(ByteAlignment);
}
-void MCMachOStreamer::EmitBytes(const StringRef &Data) {
+void MCMachOStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
if (!DF)
DF = new MCDataFragment(CurSectionData);
DF->getContents().append(Data.begin(), Data.end());
}
-void MCMachOStreamer::EmitValue(const MCValue &Value, unsigned Size) {
- new MCFillFragment(AddValueSymbols(Value), Size, 1, CurSectionData);
+void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size,
+ unsigned AddrSpace) {
+ new MCFillFragment(*AddValueSymbols(Value), Size, 1, CurSectionData);
}
void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment,
CurSectionData->setAlignment(ByteAlignment);
}
-void MCMachOStreamer::EmitValueToOffset(const MCValue &Offset,
+void MCMachOStreamer::EmitValueToOffset(const MCExpr *Offset,
unsigned char Value) {
- new MCOrgFragment(AddValueSymbols(Offset), Value, CurSectionData);
+ new MCOrgFragment(*Offset, Value, CurSectionData);
}
void MCMachOStreamer::EmitInstruction(const MCInst &Inst) {
// Scan for values.
for (unsigned i = 0; i != Inst.getNumOperands(); ++i)
- if (Inst.getOperand(i).isMCValue())
- AddValueSymbols(Inst.getOperand(i).getMCValue());
+ if (Inst.getOperand(i).isExpr())
+ AddValueSymbols(Inst.getOperand(i).getExpr());
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!
SmallString<256> Code;
raw_svector_ostream VecOS(Code);
Emitter->EncodeInstruction(Inst, VecOS);
- EmitBytes(VecOS.str());
+ EmitBytes(VecOS.str(), 0);
}
void MCMachOStreamer::Finish() {