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
This commit is contained in:
Daniel Dunbar 2009-08-27 00:51:57 +00:00
parent 81e400092f
commit 4a0abd80f1
5 changed files with 136 additions and 8 deletions

View File

@ -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

View File

@ -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

View File

@ -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<FooCodeEmitter> X(TheFooTarget);
/// }
template<class CodeEmitterImpl>
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

View File

@ -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);
}

View File

@ -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<AsmPrinter> AP;
OwningPtr<MCCodeEmitter> CE;
OwningPtr<MCStreamer> 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));