mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
Start MCAsmStreamer implementation.
llvm-svn: 74044
This commit is contained in:
parent
661e8b54fa
commit
0e5051b251
@ -17,6 +17,8 @@ namespace llvm {
|
||||
|
||||
public:
|
||||
MCAtom(MCSection *_Section) : Section(_Section) {}
|
||||
|
||||
MCSection *getSection() { return Section; }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -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.
|
||||
|
@ -19,6 +19,8 @@ namespace llvm {
|
||||
|
||||
public:
|
||||
MCSection(const char *_Name) : Name(_Name) {}
|
||||
|
||||
const std::string &getName() const { return Name; }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
143
lib/MC/MCAsmStreamer.cpp
Normal file
143
lib/MC/MCAsmStreamer.cpp
Normal 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);
|
||||
}
|
@ -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 {
|
||||
|
18
lib/MC/MCStreamer.cpp
Normal file
18
lib/MC/MCStreamer.cpp
Normal 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() {
|
||||
}
|
52
unittests/MC/AsmStreamerTest.cpp
Normal file
52
unittests/MC/AsmStreamerTest.cpp
Normal 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");
|
||||
}
|
||||
|
||||
}
|
15
unittests/MC/Makefile
Normal file
15
unittests/MC/Makefile
Normal 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
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user