public:
MCAtom(MCSection *_Section) : Section(_Section) {}
+
+ MCSection *getSection() { return Section; }
};
} // end namespace llvm
/// allocator supports it).
/// @return The allocated memory. Could be NULL.
inline void *operator new(size_t Bytes, llvm::MCContext &C,
- size_t Alignment) throw () {
+ size_t Alignment = 16) throw () {
return C.Allocate(Bytes, Alignment);
}
/// @brief Placement delete companion to the new above.
public:
MCSection(const char *_Name) : Name(_Name) {}
+
+ const std::string &getName() const { return Name; }
};
} // end namespace llvm
// the symbol and make the printer smart enough to add the right symbols?
// This should work as long as the order of attributes in the file doesn't
// matter.
- virtual void EmitSymbolAttribute(MCSymbol *Symbol,
+ virtual void EmitSymbolAttribute(MCSymbol *Symbol,
SymbolAttr Attribute) = 0;
/// EmitBytes - Emit @param Length bytes starting at @param Data into the
/// createAsmStreamer - Create a machine code streamer which will print out
/// assembly for the native target, suitable for compiling with a native
/// assembler.
- inline MCStreamer *createAsmStreamer(MCContext &Ctx, raw_ostream &OS) { return 0; }
+ MCStreamer *createAsmStreamer(MCContext &Ctx, raw_ostream &OS);
// FIXME: These two may end up getting rolled into a single
// createObjectStreamer interface, which implements the assembler backend, and
public:
MCSymbol(MCAtom *_Atom, const char *_Name, bool _IsTemporary)
: Atom(_Atom), Name(_Name), IsTemporary(_IsTemporary) {}
+
+ MCAtom *getAtom() { return Atom; }
+
+ const std::string &getName() { return Name; }
};
} // end namespace llvm
--- /dev/null
+//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCStreamer.h"
+
+#include "llvm/MC/MCAtom.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+namespace {
+
+ class MCAsmStreamer : public MCStreamer {
+ raw_ostream &OS;
+
+ MCSection *CurSection;
+
+ public:
+ MCAsmStreamer(MCContext &Context, raw_ostream &_OS)
+ : MCStreamer(Context), OS(_OS) {}
+ ~MCAsmStreamer() {}
+
+ /// @name MCStreamer Interface
+ /// @{
+
+ virtual void SwitchSection(MCSection *Section);
+
+ virtual void EmitLabel(MCSymbol *Symbol);
+
+ virtual void EmitAssignment(MCSymbol *Symbol, const MCValue &Value,
+ bool MakeAbsolute = false);
+
+ virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute);
+
+ virtual void EmitBytes(const char *Data, unsigned Length);
+
+ virtual void EmitValue(const MCValue &Value, unsigned Size);
+
+ virtual void EmitInstruction(const MCInst &Inst);
+
+ virtual void Finish();
+
+ /// @}
+ };
+
+}
+
+/// Allow printing values directly to a raw_ostream.
+inline raw_ostream &operator<<(raw_ostream &os, const MCValue &Value) {
+ if (Value.getSymA()) {
+ os << Value.getSymA()->getName();
+ if (Value.getSymB())
+ os << " - " << Value.getSymB()->getName();
+ if (Value.getCst())
+ os << " + " << Value.getCst();
+ } else {
+ assert(!Value.getSymB() && "Invalid machine code value!");
+ os << Value.getCst();
+ }
+
+ return os;
+}
+
+void MCAsmStreamer::SwitchSection(MCSection *Section) {
+ if (Section != CurSection) {
+ CurSection = Section;
+
+ // FIXME: Really we would like the segment, flags, etc. to be separate
+ // values instead of embedded in the name. Not all assemblers understand all
+ // this stuff though.
+ OS << ".section " << Section->getName() << "\n";
+ }
+}
+
+void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
+ // FIXME: We need to enforce that we aren't printing atoms which are more
+ // complicated than the assembler understands.
+ assert(Symbol->getAtom()->getSection() == CurSection &&
+ "The label for a symbol must match its section!");
+ OS << Symbol->getName() << ":\n";
+}
+
+void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCValue &Value,
+ bool MakeAbsolute) {
+ if (MakeAbsolute) {
+ OS << ".set " << Symbol->getName() << ", " << Value << '\n';
+ } else {
+ OS << Symbol->getName() << " = " << Value << '\n';
+ }
+}
+
+void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
+ SymbolAttr Attribute) {
+ switch (Attribute) {
+ case Global: OS << ".globl"; break;
+ case Weak: OS << ".weak"; break;
+ case PrivateExtern: OS << ".private_extern"; break;
+ }
+
+ OS << ' ' << Symbol->getName() << '\n';
+}
+
+void MCAsmStreamer::EmitBytes(const char *Data, unsigned Length) {
+ for (unsigned i = 0; i != Length; ++i) {
+ OS << ".byte " << (unsigned) Data[i] << '\n';
+ }
+}
+
+void MCAsmStreamer::EmitValue(const MCValue &Value, unsigned Size) {
+ // Need target hooks to know how to print this.
+ switch (Size) {
+ default:
+ assert(0 && "Invalid size for machine code value!");
+ case 1: OS << ".byte"; break;
+ case 2: OS << ".hword"; break;
+ case 4: OS << ".long"; break;
+ case 8: OS << ".quad"; break;
+ }
+
+ OS << ' ' << Value << '\n';
+}
+
+void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
+ // FIXME: Implement.
+ OS << "# FIXME: Implement instruction printing!\n";
+}
+
+void MCAsmStreamer::Finish() {
+ OS.flush();
+}
+
+MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS) {
+ return new MCAsmStreamer(Context, OS);
+}
MCSection *&Entry = Sections[Name];
if (!Entry)
- Entry = new (this) MCSection(Name);
+ Entry = new (*this) MCSection(Name);
return Entry;
}
MCAtom *MCContext::CreateAtom(MCSection *Section) {
- return new (this) MCAtom(Section);
+ return new (*this) MCAtom(Section);
}
MCSymbol *MCContext::CreateSymbol(MCAtom *Atom, const char *Name) {
// Create and bind the symbol, and ensure that names are unique.
MCSymbol *&Entry = Symbols[Name];
assert(!Entry && "Duplicate symbol definition!");
- return Entry = new (this) MCSymbol(Atom, Name, false);
+ return Entry = new (*this) MCSymbol(Atom, Name, false);
}
MCSymbol *MCContext::CreateTemporarySymbol(MCAtom *Atom, const char *Name) {
// If unnamed, just create a symbol.
if (Name[0] == '\0')
- new (this) MCSymbol(Atom, "", true);
+ new (*this) MCSymbol(Atom, "", true);
// Otherwise create as usual.
MCSymbol *&Entry = Symbols[Name];
assert(!Entry && "Duplicate symbol definition!");
- return Entry = new (this) MCSymbol(Atom, Name, true);
+ return Entry = new (*this) MCSymbol(Atom, Name, true);
}
MCSymbol *MCContext::LookupSymbol(const char *Name) const {
--- /dev/null
+//===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCStreamer.h"
+
+using namespace llvm;
+
+MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context) {
+}
+
+MCStreamer::~MCStreamer() {
+}
--- /dev/null
+//===- AsmStreamerTest.cpp - Triple unit tests ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+namespace {
+
+// Helper class.
+class StringAsmStreamer {
+ std::string Str;
+ raw_string_ostream OS;
+ MCContext Context;
+ MCStreamer *Streamer;
+
+public:
+ StringAsmStreamer() : OS(Str), Streamer(createAsmStreamer(Context, OS)) {}
+ ~StringAsmStreamer() {
+ delete Streamer;
+ }
+
+ MCContext &getContext() { return Context; }
+ MCStreamer &getStreamer() { return *Streamer; }
+
+ const std::string &getString() {
+ Streamer->Finish();
+ return Str;
+ }
+};
+
+TEST(AsmStreamer, EmptyOutput) {
+ StringAsmStreamer S;
+ EXPECT_EQ(S.getString(), "");
+}
+
+TEST(AsmStreamer, Sections) {
+ StringAsmStreamer S;
+ MCSection *Sec0 = S.getContext().GetSection("foo");
+ S.getStreamer().SwitchSection(Sec0);
+ EXPECT_EQ(S.getString(), ".section foo\n");
+}
+
+}
--- /dev/null
+##===- unittests/MC/Makefile -------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = MC
+LINK_COMPONENTS := core support mc
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include/
CPP.Flags += -Wno-variadic-macros
-PARALLEL_DIRS = ADT Support VMCore
+PARALLEL_DIRS = ADT Support VMCore MC
include $(LEVEL)/Makefile.common