diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-06-24 19:25:34 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-06-24 19:25:34 +0000 |
commit | 84a2926fb7ab388d688a133b0b375a26e669fd55 (patch) | |
tree | 15243cb6095f4f5eb5c00b47dd28a5a6998f11de | |
parent | b5299dd06a56a494e37af1656e6accf8fcbdacf4 (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.h | 45 | ||||
-rw-r--r-- | lib/MC/MCAsmStreamer.cpp | 37 | ||||
-rw-r--r-- | unittests/MC/AsmStreamerTest.cpp | 28 |
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\ +"); +} + } |