aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-06-24 19:25:34 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-06-24 19:25:34 +0000
commit84a2926fb7ab388d688a133b0b375a26e669fd55 (patch)
tree15243cb6095f4f5eb5c00b47dd28a5a6998f11de
parentb5299dd06a56a494e37af1656e6accf8fcbdacf4 (diff)
Sketch streamer support for .align, .org functionality.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74109 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/MC/MCStreamer.h45
-rw-r--r--lib/MC/MCAsmStreamer.cpp37
-rw-r--r--unittests/MC/AsmStreamerTest.cpp28
3 files changed, 110 insertions, 0 deletions
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 0ce8113d06..bb85d2d554 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -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;
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 73d6f046dc..f1f5a648bb 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -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.
diff --git a/unittests/MC/AsmStreamerTest.cpp b/unittests/MC/AsmStreamerTest.cpp
index 76da23ba54..d4b93eaadd 100644
--- a/unittests/MC/AsmStreamerTest.cpp
+++ b/unittests/MC/AsmStreamerTest.cpp
@@ -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\
+");
+}
+
}