class MCInst;
class MCInstPrinter;
class MCSection;
+class MCStreamer;
class MCSymbol;
class StringRef;
class Twine;
typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair;
+/// Target specific streamer interface. This is used so that targets can
+/// implement support for target specific assembly directives.
+///
+/// If target foo wants to use this, it should implement 3 classes:
+/// * FooTargetStreamer : public MCTargetStreamer
+/// * FooTargetAsmSreamer : public FooTargetStreamer
+/// * FooTargetELFStreamer : public FooTargetStreamer
+///
+/// FooTargetStreamer should have a pure virtual method for each directive. For
+/// example, for a ".bar symbol_name" directive, it should have
+/// virtual emitBar(const MCSymbol &Symbol) = 0;
+///
+/// The FooTargetAsmSreamer and FooTargetELFStreamer classes implement the
+/// method. The assembly streamer just prints ".bar symbol_name". The object
+/// streamer does whatever is needed to implement .bar in the object file.
+///
+/// In the assembly printer and parser the target streamer can be used by
+/// calling getTargetStreamer and casting it to FooTargetStreamer:
+///
+/// MCTargetStreamer &TS = OutStreamer.getTargetStreamer();
+/// FooTargetStreamer &ATS = static_cast<FooTargetStreamer &>(TS);
+///
+/// The base classes FooTargetAsmSreamer and FooTargetELFStreamer should *never*
+/// be treated differently. Callers should always talk to a FooTargetStreamer.
+class MCTargetStreamer {
+protected:
+ MCStreamer *Streamer;
+
+public:
+ virtual ~MCTargetStreamer();
+ void setStreamer(MCStreamer *S) { Streamer = S; }
+
+ // Allow a target to add behavior to the EmitLabel of MCStreamer.
+ virtual void emitLabel(MCSymbol *Symbol);
+};
+
+// FIXME: declared here because it is used from
+// lib/CodeGen/AsmPrinter/ARMException.cpp.
+class ARMTargetStreamer : public MCTargetStreamer {
+ virtual void anchor();
+public:
+ virtual void emitFnStart() = 0;
+ virtual void emitFnEnd() = 0;
+ virtual void emitCantUnwind() = 0;
+ virtual void emitPersonality(const MCSymbol *Personality) = 0;
+ virtual void emitHandlerData() = 0;
+ virtual void emitSetFP(unsigned FpReg, unsigned SpReg,
+ int64_t Offset = 0) = 0;
+ virtual void emitPad(int64_t Offset) = 0;
+ virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
+ bool isVector) = 0;
+
+ virtual void switchVendor(StringRef Vendor) = 0;
+ virtual void emitAttribute(unsigned Attribute, unsigned Value) = 0;
+ virtual void emitTextAttribute(unsigned Attribute, StringRef String) = 0;
+ virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
+ StringRef StringValue = "") = 0;
+ virtual void emitFPU(unsigned FPU) = 0;
+ virtual void emitArch(unsigned Arch) = 0;
+ virtual void finishAttributeSection() = 0;
+ virtual void emitInst(uint32_t Inst, char Suffix = '\0') = 0;
+};
+
/// MCStreamer - Streaming machine code generation interface. This interface
/// is intended to provide a programatic interface that is very similar to the
/// level that an assembler .s file provides. It has callbacks to emit bytes,
/// a .s file, and implementations that write out .o files of various formats.
///
class MCStreamer {
-public:
- enum StreamerKind {
- SK_AsmStreamer,
- SK_NullStreamer,
- SK_RecordStreamer,
-
- // MCObjectStreamer subclasses.
- SK_ELFStreamer,
- SK_ARMELFStreamer,
- SK_MachOStreamer,
- SK_PureStreamer,
- SK_MipsELFStreamer,
- SK_WinCOFFStreamer
- };
-
-private:
- const StreamerKind Kind;
MCContext &Context;
+ OwningPtr<MCTargetStreamer> TargetStreamer;
MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION;
MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION;
MCSymbol *LastSymbol;
+ // SymbolOrdering - Tracks an index to represent the order
+ // a symbol was emitted in. Zero means we did not emit that symbol.
+ DenseMap<const MCSymbol *, unsigned> SymbolOrdering;
+
/// SectionStack - This is stack of current and previous section
/// values saved by PushSection.
SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack;
bool AutoInitSections;
protected:
- MCStreamer(StreamerKind Kind, MCContext &Ctx);
+ MCStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer);
const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A,
const MCSymbol *B);
}
void EmitW64Tables();
+ virtual void EmitRawTextImpl(StringRef String);
+
public:
virtual ~MCStreamer();
- StreamerKind getKind() const { return Kind; }
-
/// State management
///
virtual void reset();
MCContext &getContext() const { return Context; }
+ MCTargetStreamer *getTargetStreamer() {
+ return TargetStreamer.get();
+ }
+
unsigned getNumFrameInfos() { return FrameInfos.size(); }
const MCDwarfFrameInfo &getFrameInfo(unsigned i) { return FrameInfos[i]; }
return MCSectionSubPair();
}
+ /// GetSymbolOrder - Returns an index to represent the order
+ /// a symbol was emitted in. (zero if we did not emit that symbol)
+ unsigned GetSymbolOrder(const MCSymbol *Sym) const {
+ return SymbolOrdering.lookup(Sym);
+ }
+
/// ChangeSection - Update streamer for a new active section.
///
/// This is called by PopSection and SwitchSection, if the current
/// InitToTextSection - Create a text section and switch the streamer to it.
virtual void InitToTextSection() = 0;
+ /// AssignSection - Sets the symbol's section.
+ ///
+ /// Each emitted symbol will be tracked in the ordering table,
+ /// so we can sort on them later.
+ void AssignSection(MCSymbol *Symbol, const MCSection *Section);
+
/// EmitLabel - Emit a label for @p Symbol into the current section.
///
/// This corresponds to an assembler statement such as:
/// @param Symbol - The symbol to emit. A given symbol should only be
/// emitted as a label once, and symbols emitted as a label should never be
/// used in an assignment.
+ // FIXME: These emission are non-const because we mutate the symbol to
+ // add the section we're emitting it to later.
virtual void EmitLabel(MCSymbol *Symbol);
virtual void EmitDebugLabel(MCSymbol *Symbol);
/// EndCOFFSymbolDef - Marks the end of the symbol definition.
virtual void EndCOFFSymbolDef() = 0;
+ /// EmitCOFFSectionIndex - Emits a COFF section index.
+ ///
+ /// @param Symbol - Symbol the section number relocation should point to.
+ virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol);
+
/// EmitCOFFSecRel32 - Emits a COFF section relative relocation.
///
- /// @param Symbol - Symbol the section relative realocation should point to.
+ /// @param Symbol - Symbol the section relative relocation should point to.
virtual void EmitCOFFSecRel32(MCSymbol const *Symbol);
/// EmitELFSize - Emit an ELF .size directive.
/// implement the '.file "foo.c"' assembler directive.
virtual void EmitFileDirective(StringRef Filename) = 0;
+ /// Emit the "identifiers" directive. This implements the
+ /// '.ident "version foo"' assembler directive.
+ virtual void EmitIdent(StringRef IdentString) {}
+
/// EmitDwarfFileDirective - Associate a filename with a specified logical
/// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler
/// directive.
virtual void EmitCFISignalFrame();
virtual void EmitCFIUndefined(int64_t Register);
virtual void EmitCFIRegister(int64_t Register1, int64_t Register2);
+ virtual void EmitCFIWindowSave();
virtual void EmitWin64EHStartProc(const MCSymbol *Symbol);
virtual void EmitWin64EHEndProc();
/// EmitRawText - If this file is backed by a assembly streamer, this dumps
/// the specified string in the output .s file. This capability is
/// indicated by the hasRawTextSupport() predicate. By default this aborts.
- virtual void EmitRawText(StringRef String);
void EmitRawText(const Twine &String);
- /// ARM-related methods.
- /// FIXME: Eventually we should have some "target MC streamer" and move
- /// these methods there.
- virtual void EmitFnStart();
- virtual void EmitFnEnd();
- virtual void EmitCantUnwind();
- virtual void EmitPersonality(const MCSymbol *Personality);
- virtual void EmitHandlerData();
- virtual void EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0);
- virtual void EmitPad(int64_t Offset);
- virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList,
- bool isVector);
-
- /// PPC-related methods.
- /// FIXME: Eventually replace it with some "target MC streamer" and move
- /// these methods there.
- virtual void EmitTCEntry(const MCSymbol &S);
+ /// Flush - Causes any cached state to be written out.
+ virtual void Flush() {}
/// FinishImpl - Streamer specific finalization.
virtual void FinishImpl() = 0;
///
/// \param ShowInst - Whether to show the MCInst representation inline with
/// the assembly.
-MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
- bool isVerboseAsm, bool useLoc, bool useCFI,
- bool useDwarfDirectory,
+MCStreamer *createAsmStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer,
+ formatted_raw_ostream &OS, bool isVerboseAsm,
+ bool useLoc, bool useCFI, bool useDwarfDirectory,
MCInstPrinter *InstPrint = 0,
MCCodeEmitter *CE = 0, MCAsmBackend *TAB = 0,
bool ShowInst = false);
/// createELFStreamer - Create a machine code streamer which will generate
/// ELF format object files.
-MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB,
- raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll,
+MCStreamer *createELFStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer,
+ MCAsmBackend &TAB, raw_ostream &OS,
+ MCCodeEmitter *CE, bool RelaxAll,
bool NoExecStack);
/// createPureStreamer - Create a machine code streamer which will generate