diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index 36bbe000025..1418bee00ff 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -73,6 +73,13 @@ namespace llvm { typedef MCCodeEmitter *(*CodeEmitterCtorTy)(const Target &T, TargetMachine &TM, MCContext &Ctx); + typedef MCStreamer *(*ObjectStreamerCtorTy)(const Target &T, + const std::string &TT, + MCContext &Ctx, + TargetAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll); private: /// Next - The next registered target in the linked list, maintained by the @@ -126,6 +133,10 @@ namespace llvm { /// if registered. CodeEmitterCtorTy CodeEmitterCtorFn; + /// ObjectStreamerCtorFn - Construction function for this target's + /// ObjectStreamer, if registered. + ObjectStreamerCtorTy ObjectStreamerCtorFn; + public: /// @name Target Information /// @{ @@ -170,6 +181,9 @@ namespace llvm { /// hasCodeEmitter - Check if this target supports instruction encoding. bool hasCodeEmitter() const { return CodeEmitterCtorFn != 0; } + /// hasObjectStreamer - Check if this target supports streaming to files. + bool hasObjectStreamer() const { return ObjectStreamerCtorFn != 0; } + /// @} /// @name Feature Constructors /// @{ @@ -258,6 +272,24 @@ namespace llvm { return CodeEmitterCtorFn(*this, TM, Ctx); } + /// createObjectStreamer - Create a target specific MCStreamer. + /// + /// \arg TT - The target triple. + /// \arg Ctx - The target context. + /// \arg TAB - The target assembler backend object. + /// \arg _OS - The stream object. + /// \arg _Emitter - The target independent assembler object. + /// \arg RelaxAll - Relax all fixups? + MCStreamer *createObjectStreamer(const std::string &TT, MCContext &Ctx, + TargetAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll) const { + if (!ObjectStreamerCtorFn) + return 0; + return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll); + } + /// @} }; @@ -479,6 +511,20 @@ namespace llvm { T.CodeEmitterCtorFn = Fn; } + /// RegisterObjectStreamer - Register an MCStreamer implementation + /// for the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCStreamer for the target. + static void RegisterObjectStreamer(Target &T, Target::ObjectStreamerCtorTy Fn) { + if (!T.ObjectStreamerCtorFn) + T.ObjectStreamerCtorFn = Fn; + } + /// @} }; diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index f665d92ec98..f2c50583c95 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -17,6 +17,8 @@ #include "llvm/PassManager.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" @@ -37,6 +39,18 @@ static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { } } +static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, + MCContext &Ctx, TargetAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll) { + Triple TheTriple(TT); + switch (TheTriple.getOS()) { + default: + return createMachOStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll); + } +} + extern "C" void LLVMInitializeX86Target() { // Register the target. RegisterTargetMachine X(TheX86_32Target); @@ -57,6 +71,12 @@ extern "C" void LLVMInitializeX86Target() { createX86_32AsmBackend); TargetRegistry::RegisterAsmBackend(TheX86_64Target, createX86_64AsmBackend); + + // Register the object streamer. + TargetRegistry::RegisterObjectStreamer(TheX86_32Target, + createMCStreamer); + TargetRegistry::RegisterObjectStreamer(TheX86_64Target, + createMCStreamer); } diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 18ab98e208d..ca098e17b67 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -301,7 +301,8 @@ static int AssembleInput(const char *ProgName) { assert(FileType == OFT_ObjectFile && "Invalid file type!"); CE.reset(TheTarget->createCodeEmitter(*TM, Ctx)); TAB.reset(TheTarget->createAsmBackend(TripleName)); - Str.reset(createMachOStreamer(Ctx, *TAB, *Out, CE.get(), RelaxAll)); + Str.reset(TheTarget->createObjectStreamer(TripleName, Ctx, *TAB, + *Out, CE.get(), RelaxAll)); } AsmParser Parser(SrcMgr, Ctx, *Str.get(), *MAI);