Sketch streamer support for .align, .org functionality.

llvm-svn: 74109
This commit is contained in:
Daniel Dunbar 2009-06-24 19:25:34 +00:00
parent be19db0063
commit 71ea89dd86
3 changed files with 110 additions and 0 deletions

View File

@ -10,6 +10,8 @@
#ifndef LLVM_MC_MCSTREAMER_H
#define LLVM_MC_MCSTREAMER_H
#include "llvm/Support/DataTypes.h"
namespace llvm {
class MCContext;
class MCValue;
@ -53,6 +55,9 @@ namespace llvm {
MCContext &getContext() const { return Context; }
/// @name Symbol & Section Management
/// @{
/// SwitchSection - Set the current section where code is being emitted to
/// @param Section.
///
@ -98,6 +103,10 @@ namespace llvm {
virtual void EmitSymbolAttribute(MCSymbol *Symbol,
SymbolAttr Attribute) = 0;
/// @}
/// @name Generating Data
/// @{
/// EmitBytes - Emit @param Length bytes starting at @param Data into the
/// output.
///
@ -116,6 +125,42 @@ namespace llvm {
/// match a native machine width.
virtual void EmitValue(const MCValue &Value, unsigned Size) = 0;
/// EmitValueToAlignment - Emit some number of copies of @param Value until
/// the byte alignment @param ByteAlignment is reached.
///
/// If the number of bytes need to emit for the alignment is not a multiple
/// of @param ValueSize, then the contents of the emitted fill bytes is
/// undefined.
///
/// This used to implement the .align assembler directive.
///
/// @param ByteAlignment - The alignment to reach. This must be a power of
/// two.
/// @param Value - The value to use when filling bytes.
/// @param Size - The size of the integer (in bytes) to emit for @param
/// Value. This must match a native machine width.
/// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If
/// the alignment cannot be reached in this many bytes, no bytes are
/// emitted.
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0) = 0;
/// EmitValueToOffset - Emit some number of copies of @param Value until the
/// byte offset @param Offset is reached.
///
/// This is used to implement assembler directives such as .org.
///
/// @param Offset - The offset to reach.This may be an expression, but the
/// expression must be associated with the current section.
/// @param Value - The value to use when filling bytes.
//
// FIXME: How are we going to signal failures out of this?
virtual void EmitValueToOffset(const MCValue &Offset,
unsigned char Value = 0) = 0;
/// @}
/// EmitInstruction - Emit the given @param Instruction into the current
/// section.
virtual void EmitInstruction(const MCInst &Inst) = 0;

View File

@ -44,6 +44,13 @@ namespace {
virtual void EmitValue(const MCValue &Value, unsigned Size);
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0);
virtual void EmitValueToOffset(const MCValue &Offset,
unsigned char Value = 0);
virtual void EmitInstruction(const MCInst &Inst);
virtual void Finish();
@ -144,6 +151,36 @@ void MCAsmStreamer::EmitValue(const MCValue &Value, unsigned Size) {
OS << ' ' << Value << '\n';
}
void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
unsigned ValueSize,
unsigned MaxBytesToEmit) {
unsigned Pow2 = Log2_32(ByteAlignment);
assert((1U << Pow2) == ByteAlignment && "Invalid alignment!");
switch (ValueSize) {
default:
assert(0 && "Invalid size for machine code value!");
case 8:
assert(0 && "Unsupported alignment size!");
case 1: OS << ".p2align"; break;
case 2: OS << ".p2alignw"; break;
case 4: OS << ".p2alignl"; break;
}
OS << ' ' << Pow2;
OS << ", " << Value;
if (MaxBytesToEmit)
OS << ", " << MaxBytesToEmit;
OS << '\n';
}
void MCAsmStreamer::EmitValueToOffset(const MCValue &Offset,
unsigned char Value) {
// FIXME: Verify that Offset is associated with the current section.
OS << ".org " << Offset << ", " << (unsigned) Value << '\n';
}
void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
assert(CurSection && "Cannot emit contents before setting section!");
// FIXME: Implement.

View File

@ -72,4 +72,32 @@ b:\n\
");
}
TEST(AsmStreamer, Align) {
StringAsmStreamer S;
MCSection *Sec0 = S.getContext().GetSection("foo");
S.getStreamer().SwitchSection(Sec0);
S.getStreamer().EmitValueToAlignment(4);
S.getStreamer().EmitValueToAlignment(4, /*Value=*/12, /*ValueSize=*/2);
S.getStreamer().EmitValueToAlignment(8, /*Value=*/12, /*ValueSize=*/4,
/*MaxBytesToEmit=*/24);
EXPECT_EQ(S.getString(), ".section foo\n\
.p2align 2, 0\n\
.p2alignw 2, 12\n\
.p2alignl 3, 12, 24\n\
");
}
TEST(AsmStreamer, Org) {
StringAsmStreamer S;
MCSection *Sec0 = S.getContext().GetSection("foo");
S.getStreamer().SwitchSection(Sec0);
MCSymbol *A = S.getContext().CreateSymbol("a");
S.getStreamer().EmitLabel(A);
S.getStreamer().EmitValueToOffset(MCValue::get(A, 0, 4), 32);
EXPECT_EQ(S.getString(), ".section foo\n\
a:\n\
.org a + 4, 32\n\
");
}
}