1 //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output --------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/MC/MCStreamer.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/CodeGen/AsmPrinter.h"
13 #include "llvm/MC/MCAsmInfo.h"
14 #include "llvm/MC/MCCodeEmitter.h"
15 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/MC/MCSectionMachO.h"
19 #include "llvm/MC/MCSymbol.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/MathExtras.h"
22 #include "llvm/Support/Format.h"
23 #include "llvm/Support/raw_ostream.h"
28 class MCAsmStreamer
: public MCStreamer
{
32 MCCodeEmitter
*Emitter
;
34 MCAsmStreamer(MCContext
&Context
, raw_ostream
&_OS
, const MCAsmInfo
&tai
,
35 AsmPrinter
*_Printer
, MCCodeEmitter
*_Emitter
)
36 : MCStreamer(Context
), OS(_OS
), MAI(tai
), Printer(_Printer
),
40 /// @name MCStreamer Interface
43 virtual void SwitchSection(const MCSection
*Section
);
45 virtual void EmitLabel(MCSymbol
*Symbol
);
47 virtual void EmitAssemblerFlag(AssemblerFlag Flag
);
49 virtual void EmitAssignment(MCSymbol
*Symbol
, const MCExpr
*Value
);
51 virtual void EmitSymbolAttribute(MCSymbol
*Symbol
, SymbolAttr Attribute
);
53 virtual void EmitSymbolDesc(MCSymbol
*Symbol
, unsigned DescValue
);
55 virtual void EmitCommonSymbol(MCSymbol
*Symbol
, unsigned Size
,
56 unsigned ByteAlignment
);
58 virtual void EmitZerofill(const MCSection
*Section
, MCSymbol
*Symbol
= 0,
59 unsigned Size
= 0, unsigned ByteAlignment
= 0);
61 virtual void EmitBytes(const StringRef
&Data
);
63 virtual void EmitValue(const MCExpr
*Value
, unsigned Size
);
65 virtual void EmitValueToAlignment(unsigned ByteAlignment
, int64_t Value
= 0,
66 unsigned ValueSize
= 1,
67 unsigned MaxBytesToEmit
= 0);
69 virtual void EmitValueToOffset(const MCExpr
*Offset
,
70 unsigned char Value
= 0);
72 virtual void EmitInstruction(const MCInst
&Inst
);
74 virtual void Finish();
79 } // end anonymous namespace.
81 static inline int64_t truncateToSize(int64_t Value
, unsigned Bytes
) {
82 assert(Bytes
&& "Invalid size!");
83 return Value
& ((uint64_t) (int64_t) -1 >> (64 - Bytes
* 8));
86 static inline const MCExpr
*truncateToSize(const MCExpr
*Value
,
88 // FIXME: Do we really need this routine?
92 void MCAsmStreamer::SwitchSection(const MCSection
*Section
) {
93 assert(Section
&& "Cannot switch to a null section!");
94 if (Section
!= CurSection
) {
96 Section
->PrintSwitchToSection(MAI
, OS
);
100 void MCAsmStreamer::EmitLabel(MCSymbol
*Symbol
) {
101 assert(Symbol
->isUndefined() && "Cannot define a symbol twice!");
102 assert(CurSection
&& "Cannot emit before setting section!");
104 Symbol
->print(OS
, &MAI
);
106 Symbol
->setSection(*CurSection
);
109 void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag
) {
111 default: assert(0 && "Invalid flag!");
112 case SubsectionsViaSymbols
: OS
<< ".subsections_via_symbols"; break;
117 void MCAsmStreamer::EmitAssignment(MCSymbol
*Symbol
, const MCExpr
*Value
) {
118 // Only absolute symbols can be redefined.
119 assert((Symbol
->isUndefined() || Symbol
->isAbsolute()) &&
120 "Cannot define a symbol twice!");
122 Symbol
->print(OS
, &MAI
);
124 Value
->print(OS
, &MAI
);
128 void MCAsmStreamer::EmitSymbolAttribute(MCSymbol
*Symbol
,
129 SymbolAttr Attribute
) {
131 case Global
: OS
<< ".globl"; break;
132 case Hidden
: OS
<< ".hidden"; break;
133 case IndirectSymbol
: OS
<< ".indirect_symbol"; break;
134 case Internal
: OS
<< ".internal"; break;
135 case LazyReference
: OS
<< ".lazy_reference"; break;
136 case NoDeadStrip
: OS
<< ".no_dead_strip"; break;
137 case PrivateExtern
: OS
<< ".private_extern"; break;
138 case Protected
: OS
<< ".protected"; break;
139 case Reference
: OS
<< ".reference"; break;
140 case Weak
: OS
<< ".weak"; break;
141 case WeakDefinition
: OS
<< ".weak_definition"; break;
142 case WeakReference
: OS
<< ".weak_reference"; break;
146 Symbol
->print(OS
, &MAI
);
150 void MCAsmStreamer::EmitSymbolDesc(MCSymbol
*Symbol
, unsigned DescValue
) {
151 OS
<< ".desc" << ' ';
152 Symbol
->print(OS
, &MAI
);
153 OS
<< ',' << DescValue
<< '\n';
156 void MCAsmStreamer::EmitCommonSymbol(MCSymbol
*Symbol
, unsigned Size
,
157 unsigned ByteAlignment
) {
159 Symbol
->print(OS
, &MAI
);
161 if (ByteAlignment
!= 0)
162 OS
<< ',' << Log2_32(ByteAlignment
);
166 void MCAsmStreamer::EmitZerofill(const MCSection
*Section
, MCSymbol
*Symbol
,
167 unsigned Size
, unsigned ByteAlignment
) {
168 // Note: a .zerofill directive does not switch sections.
171 // This is a mach-o specific directive.
172 const MCSectionMachO
*MOSection
= ((const MCSectionMachO
*)Section
);
173 OS
<< MOSection
->getSegmentName() << "," << MOSection
->getSectionName();
175 if (Symbol
!= NULL
) {
177 Symbol
->print(OS
, &MAI
);
179 if (ByteAlignment
!= 0)
180 OS
<< ',' << Log2_32(ByteAlignment
);
185 void MCAsmStreamer::EmitBytes(const StringRef
&Data
) {
186 assert(CurSection
&& "Cannot emit contents before setting section!");
187 for (unsigned i
= 0, e
= Data
.size(); i
!= e
; ++i
)
188 OS
<< ".byte " << (unsigned) (unsigned char) Data
[i
] << '\n';
191 void MCAsmStreamer::EmitValue(const MCExpr
*Value
, unsigned Size
) {
192 assert(CurSection
&& "Cannot emit contents before setting section!");
193 // Need target hooks to know how to print this.
196 llvm_unreachable("Invalid size for machine code value!");
197 case 1: OS
<< ".byte"; break;
198 case 2: OS
<< ".short"; break;
199 case 4: OS
<< ".long"; break;
200 case 8: OS
<< ".quad"; break;
204 truncateToSize(Value
, Size
)->print(OS
, &MAI
);
208 void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment
, int64_t Value
,
210 unsigned MaxBytesToEmit
) {
211 // Some assemblers don't support non-power of two alignments, so we always
212 // emit alignments as a power of two if possible.
213 if (isPowerOf2_32(ByteAlignment
)) {
215 default: llvm_unreachable("Invalid size for machine code value!");
216 case 1: OS
<< MAI
.getAlignDirective(); break;
217 // FIXME: use MAI for this!
218 case 2: OS
<< ".p2alignw "; break;
219 case 4: OS
<< ".p2alignl "; break;
220 case 8: llvm_unreachable("Unsupported alignment size!");
223 if (MAI
.getAlignmentIsInBytes())
226 OS
<< Log2_32(ByteAlignment
);
228 if (Value
|| MaxBytesToEmit
) {
230 OS
.write_hex(truncateToSize(Value
, ValueSize
));
233 OS
<< ", " << MaxBytesToEmit
;
239 // Non-power of two alignment. This is not widely supported by assemblers.
240 // FIXME: Parameterize this based on MAI.
242 default: llvm_unreachable("Invalid size for machine code value!");
243 case 1: OS
<< ".balign"; break;
244 case 2: OS
<< ".balignw"; break;
245 case 4: OS
<< ".balignl"; break;
246 case 8: llvm_unreachable("Unsupported alignment size!");
249 OS
<< ' ' << ByteAlignment
;
250 OS
<< ", " << truncateToSize(Value
, ValueSize
);
252 OS
<< ", " << MaxBytesToEmit
;
256 void MCAsmStreamer::EmitValueToOffset(const MCExpr
*Offset
,
257 unsigned char Value
) {
258 // FIXME: Verify that Offset is associated with the current section.
260 Offset
->print(OS
, &MAI
);
261 OS
<< ", " << (unsigned) Value
<< '\n';
264 void MCAsmStreamer::EmitInstruction(const MCInst
&Inst
) {
265 assert(CurSection
&& "Cannot emit contents before setting section!");
267 // If we have an AsmPrinter, use that to print.
269 Printer
->printMCInst(&Inst
);
272 // Show the encoding if we have a code emitter.
274 SmallString
<256> Code
;
275 raw_svector_ostream
VecOS(Code
);
276 Emitter
->EncodeInstruction(Inst
, VecOS
);
280 OS
<< " # encoding: [";
281 for (unsigned i
= 0, e
= Code
.size(); i
!= e
; ++i
) {
284 OS
<< format("%#04x", uint8_t(Code
[i
]));
292 // Otherwise fall back to a structural printing for now. Eventually we should
293 // always have access to the target specific printer.
294 Inst
.print(OS
, &MAI
);
298 void MCAsmStreamer::Finish() {
302 MCStreamer
*llvm::createAsmStreamer(MCContext
&Context
, raw_ostream
&OS
,
303 const MCAsmInfo
&MAI
, AsmPrinter
*AP
,
305 return new MCAsmStreamer(Context
, OS
, MAI
, AP
, CE
);