Start MCAsmStreamer implementation.

llvm-svn: 74044
This commit is contained in:
Daniel Dunbar 2009-06-24 01:03:06 +00:00
parent 9ef415edf2
commit 9faf273fc4
11 changed files with 245 additions and 9 deletions

View File

@ -17,6 +17,8 @@ namespace llvm {
public:
MCAtom(MCSection *_Section) : Section(_Section) {}
MCSection *getSection() { return Section; }
};
} // end namespace llvm

View File

@ -113,7 +113,7 @@ 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.

View File

@ -19,6 +19,8 @@ namespace llvm {
public:
MCSection(const char *_Name) : Name(_Name) {}
const std::string &getName() const { return Name; }
};
} // end namespace llvm

View File

@ -84,7 +84,7 @@ 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
@ -116,7 +116,7 @@ namespace llvm {
/// 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

View File

@ -23,6 +23,10 @@ namespace llvm {
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

View File

@ -0,0 +1,143 @@
//===- 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);
}

View File

@ -26,13 +26,13 @@ MCSection *MCContext::GetSection(const char *Name) {
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) {
@ -41,18 +41,18 @@ 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 {

View File

@ -0,0 +1,18 @@
//===- 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() {
}

View File

@ -0,0 +1,52 @@
//===- 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");
}
}

View File

@ -0,0 +1,15 @@
##===- 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

View File

@ -16,7 +16,7 @@ BUILD_ARCHIVE = 1
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