aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCCodeEmitter.h32
-rw-r--r--include/llvm/MC/MCStreamer.h8
-rw-r--r--include/llvm/Target/TargetRegistry.h68
-rw-r--r--lib/MC/MCAsmStreamer.cpp31
-rw-r--r--tools/llvm-mc/llvm-mc.cpp5
5 files changed, 136 insertions, 8 deletions
diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h
new file mode 100644
index 0000000..fdacb94
--- /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 e774104..bc7f543 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 6772d06..14fbd45 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<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
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 76d6ee6..9ea9b43 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 a9c7fe1..c7f626c 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<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));