From 4a0abd80f18f9c2a10bf5b14cd6731d51972a426 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 27 Aug 2009 00:51:57 +0000 Subject: [PATCH] Sketch TargetRegistry support for MCCodeEmitter abstract interface. - Of course, nothing actually can provide this interface yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80188 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCCodeEmitter.h | 32 +++++++++++++ include/llvm/MC/MCStreamer.h | 8 ++-- include/llvm/Target/TargetRegistry.h | 68 ++++++++++++++++++++++++++++ lib/MC/MCAsmStreamer.cpp | 31 +++++++++++-- tools/llvm-mc/llvm-mc.cpp | 5 +- 5 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 include/llvm/MC/MCCodeEmitter.h diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h new file mode 100644 index 00000000000..fdacb942827 --- /dev/null +++ b/include/llvm/MC/MCCodeEmitter.h @@ -0,0 +1,32 @@ +//===-- llvm/MC/MCCodeEmitter.h - Instruction Encoding ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCCODEEMITTER_H +#define LLVM_MC_MCCODEEMITTER_H + +namespace llvm { + +/// MCCodeEmitter - Generic instruction encoding interface. +class MCCodeEmitter { + MCCodeEmitter(const MCCodeEmitter &); // DO NOT IMPLEMENT + void operator=(const MCCodeEmitter &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + MCCodeEmitter(); + +public: + virtual ~MCCodeEmitter(); + + /// EncodeInstruction - Encode the given \arg Inst to bytes on the output + /// stream \arg OS. + virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS) = 0; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index e7741042e74..bc7f5433225 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -18,14 +18,15 @@ namespace llvm { class AsmPrinter; + class MCAsmInfo; + class MCCodeEmitter; class MCContext; - class MCValue; class MCInst; class MCSection; class MCSymbol; + class MCValue; class StringRef; class raw_ostream; - class MCAsmInfo; /// MCStreamer - Streaming machine code generation interface. This interface /// is intended to provide a programatic interface that is very similar to the @@ -241,7 +242,8 @@ namespace llvm { /// /// \arg AP - If given, an AsmPrinter to use for printing instructions. MCStreamer *createAsmStreamer(MCContext &Ctx, raw_ostream &OS, - const MCAsmInfo &MAI, AsmPrinter *AP = 0); + const MCAsmInfo &MAI, AsmPrinter *AP = 0, + MCCodeEmitter *CE = 0); // FIXME: These two may end up getting rolled into a single // createObjectStreamer interface, which implements the assembler backend, and diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index 6772d061eec..14fbd45e991 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -26,6 +26,7 @@ namespace llvm { class AsmPrinter; class MCAsmParser; + class MCCodeEmitter; class Module; class MCAsmInfo; class TargetAsmParser; @@ -57,6 +58,10 @@ namespace llvm { bool VerboseAsm); typedef TargetAsmParser *(*AsmParserCtorTy)(const Target &T, MCAsmParser &P); + typedef MCCodeEmitter *(*CodeEmitterCtorTy)(const Target &T, + TargetMachine &TM, + const MCAsmInfo &MAI); + private: /// Next - The next registered target in the linked list, maintained by the /// TargetRegistry. @@ -89,7 +94,14 @@ namespace llvm { /// if registered. AsmParserCtorTy AsmParserCtorFn; + /// CodeEmitterCtorFn - Construction function for this target's CodeEmitter, + /// if registered. + CodeEmitterCtorTy CodeEmitterCtorFn; + public: + /// @name Target Information + /// @{ + // getNext - Return the next registered target. const Target *getNext() const { return Next; } @@ -99,6 +111,11 @@ namespace llvm { /// getShortDescription - Get a short description of the target. const char *getShortDescription() const { return ShortDesc; } + /// @} + /// @name Feature Predicates + /// @{ + + /// hasJIT - Check if this targets supports the just-in-time compilation. bool hasJIT() const { return HasJIT; } /// hasTargetMachine - Check if this target supports code generation. @@ -110,6 +127,12 @@ namespace llvm { /// hasAsmParser - Check if this target supports .s parsing. bool hasAsmParser() const { return AsmParserCtorFn != 0; } + /// hasCodeEmitter - Check if this target supports instruction encoding. + bool hasCodeEmitter() const { return CodeEmitterCtorFn != 0; } + + /// @} + /// @name Feature Constructors + /// @{ /// createAsmInfo - Create a MCAsmInfo implementation for the specified /// target triple. @@ -155,6 +178,16 @@ namespace llvm { return 0; return AsmParserCtorFn(*this, Parser); } + + /// createCodeEmitter - Create a target specific code emitter. + MCCodeEmitter *createCodeEmitter(TargetMachine &TM, + const MCAsmInfo *MAI) const { + if (!CodeEmitterCtorFn) + return 0; + return CodeEmitterCtorFn(*this, TM, *MAI); + } + + /// @} }; /// TargetRegistry - Generic interface to target specific features. @@ -303,6 +336,20 @@ namespace llvm { T.AsmParserCtorFn = Fn; } + /// RegisterCodeEmitter - Register a MCCodeEmitter 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 AsmPrinter for the target. + static void RegisterCodeEmitter(Target &T, Target::CodeEmitterCtorTy Fn) { + if (!T.CodeEmitterCtorFn) + T.CodeEmitterCtorFn = Fn; + } + /// @} }; @@ -431,6 +478,27 @@ namespace llvm { } }; + /// RegisterCodeEmitter - Helper template for registering a target specific + /// machine code emitter, for use in the target initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooCodeEmitter() { + /// extern Target TheFooTarget; + /// RegisterCodeEmitter X(TheFooTarget); + /// } + template + struct RegisterCodeEmitter { + RegisterCodeEmitter(Target &T) { + TargetRegistry::RegisterCodeEmitter(T, &Allocator); + } + + private: + static MCCodeEmitter *Allocator(const Target &T, TargetMachine &TM, + const MCAsmInfo &MAI) { + return new CodeEmitterImpl(T, TM, MAI); + } + }; + } #endif diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 76d6ee687bd..9ea9b4342ca 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -8,7 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCStreamer.h" +#include "llvm/ADT/SmallString.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSectionMachO.h" @@ -17,6 +19,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -26,10 +29,12 @@ class MCAsmStreamer : public MCStreamer { raw_ostream &OS; const MCAsmInfo &MAI; AsmPrinter *Printer; + MCCodeEmitter *Emitter; public: MCAsmStreamer(MCContext &Context, raw_ostream &_OS, const MCAsmInfo &tai, - AsmPrinter *_AsmPrinter) - : MCStreamer(Context), OS(_OS), MAI(tai), Printer(_AsmPrinter) {} + AsmPrinter *_Printer, MCCodeEmitter *_Emitter) + : MCStreamer(Context), OS(_OS), MAI(tai), Printer(_Printer), + Emitter(_Emitter) {} ~MCAsmStreamer() {} /// @name MCStreamer Interface @@ -290,6 +295,23 @@ static raw_ostream &operator<<(raw_ostream &OS, const MCOperand &Op) { void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { assert(CurSection && "Cannot emit contents before setting section!"); + // Show the encoding if we have a code emitter. + if (Emitter) { + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + Emitter->EncodeInstruction(Inst, VecOS); + VecOS.flush(); + + OS.indent(20); + OS << " # encoding: ["; + for (unsigned i = 0, e = Code.size(); i != e; ++i) { + if (i + 1 != e) + OS << ','; + OS << format("%#04x", Code[i]); + } + OS << "]\n"; + } + // If we have an AsmPrinter, use that to print. if (Printer) { Printer->printMCInst(&Inst); @@ -314,6 +336,7 @@ void MCAsmStreamer::Finish() { } MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS, - const MCAsmInfo &MAI, AsmPrinter *AP) { - return new MCAsmStreamer(Context, OS, MAI, AP); + const MCAsmInfo &MAI, AsmPrinter *AP, + MCCodeEmitter *CE) { + return new MCAsmStreamer(Context, OS, MAI, AP, CE); } diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index a9c7fe19399..c7f626c8ad0 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/ADT/OwningPtr.h" @@ -235,6 +236,7 @@ static int AssembleInput(const char *ProgName) { } OwningPtr AP; + OwningPtr CE; OwningPtr Str; if (FileType == OFT_AssemblyFile) { @@ -242,7 +244,8 @@ static int AssembleInput(const char *ProgName) { assert(TAI && "Unable to create target asm info!"); AP.reset(TheTarget->createAsmPrinter(*Out, *TM, TAI, true)); - Str.reset(createAsmStreamer(Ctx, *Out, *TAI, AP.get())); + CE.reset(TheTarget->createCodeEmitter(*TM, TAI)); + Str.reset(createAsmStreamer(Ctx, *Out, *TAI, AP.get(), CE.get())); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); Str.reset(createMachOStreamer(Ctx, *Out));