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/MC/MCAsmInfo.h"
12 #include "llvm/MC/MCCodeEmitter.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCInstPrinter.h"
17 #include "llvm/MC/MCSectionMachO.h"
18 #include "llvm/MC/MCSymbol.h"
19 #include "llvm/ADT/OwningPtr.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/Twine.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/MathExtras.h"
24 #include "llvm/Support/Format.h"
25 #include "llvm/Support/FormattedStream.h"
30 class MCAsmStreamer
: public MCStreamer
{
31 formatted_raw_ostream
&OS
;
33 OwningPtr
<MCInstPrinter
> InstPrinter
;
34 OwningPtr
<MCCodeEmitter
> Emitter
;
36 SmallString
<128> CommentToEmit
;
37 raw_svector_ostream CommentStream
;
39 unsigned IsLittleEndian
: 1;
40 unsigned IsVerboseAsm
: 1;
41 unsigned ShowInst
: 1;
44 MCAsmStreamer(MCContext
&Context
, formatted_raw_ostream
&os
,
45 bool isLittleEndian
, bool isVerboseAsm
, MCInstPrinter
*printer
,
46 MCCodeEmitter
*emitter
, bool showInst
)
47 : MCStreamer(Context
), OS(os
), MAI(Context
.getAsmInfo()),
48 InstPrinter(printer
), Emitter(emitter
), CommentStream(CommentToEmit
),
49 IsLittleEndian(isLittleEndian
), IsVerboseAsm(isVerboseAsm
),
51 if (InstPrinter
&& IsVerboseAsm
)
52 InstPrinter
->setCommentStream(CommentStream
);
56 bool isLittleEndian() const { return IsLittleEndian
; }
58 inline void EmitEOL() {
59 // If we don't have any comments, just emit a \n.
66 void EmitCommentsAndEOL();
68 /// isVerboseAsm - Return true if this streamer supports verbose assembly at
70 virtual bool isVerboseAsm() const { return IsVerboseAsm
; }
72 /// hasRawTextSupport - We support EmitRawText.
73 virtual bool hasRawTextSupport() const { return true; }
75 /// AddComment - Add a comment that can be emitted to the generated .s
76 /// file if applicable as a QoI issue to make the output of the compiler
77 /// more readable. This only affects the MCAsmStreamer, and only when
78 /// verbose assembly output is enabled.
79 virtual void AddComment(const Twine
&T
);
81 /// AddEncodingComment - Add a comment showing the encoding of an instruction.
82 virtual void AddEncodingComment(const MCInst
&Inst
);
84 /// GetCommentOS - Return a raw_ostream that comments can be written to.
85 /// Unlike AddComment, you are required to terminate comments with \n if you
87 virtual raw_ostream
&GetCommentOS() {
89 return nulls(); // Discard comments unless in verbose asm mode.
93 /// AddBlankLine - Emit a blank line to a .s file to pretty it up.
94 virtual void AddBlankLine() {
98 /// @name MCStreamer Interface
101 virtual void SwitchSection(const MCSection
*Section
);
103 virtual void InitSections() {
104 // FIXME, this is MachO specific, but the testsuite
106 SwitchSection(getContext().getMachOSection("__TEXT", "__text",
107 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS
,
108 0, SectionKind::getText()));
111 virtual void EmitLabel(MCSymbol
*Symbol
);
113 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag
);
115 virtual void EmitAssignment(MCSymbol
*Symbol
, const MCExpr
*Value
);
116 virtual void EmitWeakReference(MCSymbol
*Alias
, const MCSymbol
*Symbol
);
118 virtual void EmitSymbolAttribute(MCSymbol
*Symbol
, MCSymbolAttr Attribute
);
120 virtual void EmitSymbolDesc(MCSymbol
*Symbol
, unsigned DescValue
);
121 virtual void BeginCOFFSymbolDef(const MCSymbol
*Symbol
);
122 virtual void EmitCOFFSymbolStorageClass(int StorageClass
);
123 virtual void EmitCOFFSymbolType(int Type
);
124 virtual void EndCOFFSymbolDef();
125 virtual void EmitELFSize(MCSymbol
*Symbol
, const MCExpr
*Value
);
126 virtual void EmitCommonSymbol(MCSymbol
*Symbol
, uint64_t Size
,
127 unsigned ByteAlignment
);
129 /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
131 /// @param Symbol - The common symbol to emit.
132 /// @param Size - The size of the common symbol.
133 virtual void EmitLocalCommonSymbol(MCSymbol
*Symbol
, uint64_t Size
);
135 virtual void EmitZerofill(const MCSection
*Section
, MCSymbol
*Symbol
= 0,
136 unsigned Size
= 0, unsigned ByteAlignment
= 0);
138 virtual void EmitTBSSSymbol (const MCSection
*Section
, MCSymbol
*Symbol
,
139 uint64_t Size
, unsigned ByteAlignment
= 0);
141 virtual void EmitBytes(StringRef Data
, unsigned AddrSpace
);
143 virtual void EmitValue(const MCExpr
*Value
, unsigned Size
,unsigned AddrSpace
);
145 virtual void EmitIntValue(uint64_t Value
, unsigned Size
, unsigned AddrSpace
);
147 virtual void EmitULEB128Value(const MCExpr
*Value
, unsigned AddrSpace
= 0);
149 virtual void EmitSLEB128Value(const MCExpr
*Value
, unsigned AddrSpace
= 0);
151 virtual void EmitGPRel32Value(const MCExpr
*Value
);
154 virtual void EmitFill(uint64_t NumBytes
, uint8_t FillValue
,
157 virtual void EmitValueToAlignment(unsigned ByteAlignment
, int64_t Value
= 0,
158 unsigned ValueSize
= 1,
159 unsigned MaxBytesToEmit
= 0);
161 virtual void EmitCodeAlignment(unsigned ByteAlignment
,
162 unsigned MaxBytesToEmit
= 0);
164 virtual void EmitValueToOffset(const MCExpr
*Offset
,
165 unsigned char Value
= 0);
167 virtual void EmitFileDirective(StringRef Filename
);
168 virtual void EmitDwarfFileDirective(unsigned FileNo
, StringRef Filename
);
170 virtual void EmitInstruction(const MCInst
&Inst
);
172 /// EmitRawText - If this file is backed by an assembly streamer, this dumps
173 /// the specified string in the output .s file. This capability is
174 /// indicated by the hasRawTextSupport() predicate.
175 virtual void EmitRawText(StringRef String
);
177 virtual void Finish();
182 } // end anonymous namespace.
184 /// AddComment - Add a comment that can be emitted to the generated .s
185 /// file if applicable as a QoI issue to make the output of the compiler
186 /// more readable. This only affects the MCAsmStreamer, and only when
187 /// verbose assembly output is enabled.
188 void MCAsmStreamer::AddComment(const Twine
&T
) {
189 if (!IsVerboseAsm
) return;
191 // Make sure that CommentStream is flushed.
192 CommentStream
.flush();
194 T
.toVector(CommentToEmit
);
195 // Each comment goes on its own line.
196 CommentToEmit
.push_back('\n');
198 // Tell the comment stream that the vector changed underneath it.
199 CommentStream
.resync();
202 void MCAsmStreamer::EmitCommentsAndEOL() {
203 if (CommentToEmit
.empty() && CommentStream
.GetNumBytesInBuffer() == 0) {
208 CommentStream
.flush();
209 StringRef Comments
= CommentToEmit
.str();
211 assert(Comments
.back() == '\n' &&
212 "Comment array not newline terminated");
214 // Emit a line of comments.
215 OS
.PadToColumn(MAI
.getCommentColumn());
216 size_t Position
= Comments
.find('\n');
217 OS
<< MAI
.getCommentString() << ' ' << Comments
.substr(0, Position
) << '\n';
219 Comments
= Comments
.substr(Position
+1);
220 } while (!Comments
.empty());
222 CommentToEmit
.clear();
223 // Tell the comment stream that the vector changed underneath it.
224 CommentStream
.resync();
227 static inline int64_t truncateToSize(int64_t Value
, unsigned Bytes
) {
228 assert(Bytes
&& "Invalid size!");
229 return Value
& ((uint64_t) (int64_t) -1 >> (64 - Bytes
* 8));
232 void MCAsmStreamer::SwitchSection(const MCSection
*Section
) {
233 assert(Section
&& "Cannot switch to a null section!");
234 if (Section
!= CurSection
) {
235 PrevSection
= CurSection
;
236 CurSection
= Section
;
237 Section
->PrintSwitchToSection(MAI
, OS
);
241 void MCAsmStreamer::EmitLabel(MCSymbol
*Symbol
) {
242 assert(Symbol
->isUndefined() && "Cannot define a symbol twice!");
243 assert(!Symbol
->isVariable() && "Cannot emit a variable symbol!");
244 assert(CurSection
&& "Cannot emit before setting section!");
246 OS
<< *Symbol
<< MAI
.getLabelSuffix();
248 Symbol
->setSection(*CurSection
);
251 void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag
) {
253 default: assert(0 && "Invalid flag!");
254 case MCAF_SyntaxUnified
: OS
<< "\t.syntax unified"; break;
255 case MCAF_SubsectionsViaSymbols
: OS
<< ".subsections_via_symbols"; break;
260 void MCAsmStreamer::EmitAssignment(MCSymbol
*Symbol
, const MCExpr
*Value
) {
261 OS
<< *Symbol
<< " = " << *Value
;
264 // FIXME: Lift context changes into super class.
265 Symbol
->setVariableValue(Value
);
268 void MCAsmStreamer::EmitWeakReference(MCSymbol
*Alias
, const MCSymbol
*Symbol
) {
269 OS
<< ".weakref " << *Alias
<< ", " << *Symbol
;
273 void MCAsmStreamer::EmitSymbolAttribute(MCSymbol
*Symbol
,
274 MCSymbolAttr Attribute
) {
276 case MCSA_Invalid
: assert(0 && "Invalid symbol attribute");
277 case MCSA_ELF_TypeFunction
: /// .type _foo, STT_FUNC # aka @function
278 case MCSA_ELF_TypeIndFunction
: /// .type _foo, STT_GNU_IFUNC
279 case MCSA_ELF_TypeObject
: /// .type _foo, STT_OBJECT # aka @object
280 case MCSA_ELF_TypeTLS
: /// .type _foo, STT_TLS # aka @tls_object
281 case MCSA_ELF_TypeCommon
: /// .type _foo, STT_COMMON # aka @common
282 case MCSA_ELF_TypeNoType
: /// .type _foo, STT_NOTYPE # aka @notype
283 assert(MAI
.hasDotTypeDotSizeDirective() && "Symbol Attr not supported");
284 OS
<< "\t.type\t" << *Symbol
<< ','
285 << ((MAI
.getCommentString()[0] != '@') ? '@' : '%');
287 default: assert(0 && "Unknown ELF .type");
288 case MCSA_ELF_TypeFunction
: OS
<< "function"; break;
289 case MCSA_ELF_TypeIndFunction
: OS
<< "gnu_indirect_function"; break;
290 case MCSA_ELF_TypeObject
: OS
<< "object"; break;
291 case MCSA_ELF_TypeTLS
: OS
<< "tls_object"; break;
292 case MCSA_ELF_TypeCommon
: OS
<< "common"; break;
293 case MCSA_ELF_TypeNoType
: OS
<< "no_type"; break;
297 case MCSA_Global
: // .globl/.global
298 OS
<< MAI
.getGlobalDirective();
300 case MCSA_Hidden
: OS
<< "\t.hidden\t"; break;
301 case MCSA_IndirectSymbol
: OS
<< "\t.indirect_symbol\t"; break;
302 case MCSA_Internal
: OS
<< "\t.internal\t"; break;
303 case MCSA_LazyReference
: OS
<< "\t.lazy_reference\t"; break;
304 case MCSA_Local
: OS
<< "\t.local\t"; break;
305 case MCSA_NoDeadStrip
: OS
<< "\t.no_dead_strip\t"; break;
306 case MCSA_PrivateExtern
: OS
<< "\t.private_extern\t"; break;
307 case MCSA_Protected
: OS
<< "\t.protected\t"; break;
308 case MCSA_Reference
: OS
<< "\t.reference\t"; break;
309 case MCSA_Weak
: OS
<< "\t.weak\t"; break;
310 case MCSA_WeakDefinition
: OS
<< "\t.weak_definition\t"; break;
312 case MCSA_WeakReference
: OS
<< MAI
.getWeakRefDirective(); break;
313 case MCSA_WeakDefAutoPrivate
: OS
<< "\t.weak_def_can_be_hidden\t"; break;
320 void MCAsmStreamer::EmitSymbolDesc(MCSymbol
*Symbol
, unsigned DescValue
) {
321 OS
<< ".desc" << ' ' << *Symbol
<< ',' << DescValue
;
325 void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol
*Symbol
) {
326 OS
<< "\t.def\t " << *Symbol
<< ';';
330 void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass
) {
331 OS
<< "\t.scl\t" << StorageClass
<< ';';
335 void MCAsmStreamer::EmitCOFFSymbolType (int Type
) {
336 OS
<< "\t.type\t" << Type
<< ';';
340 void MCAsmStreamer::EndCOFFSymbolDef() {
345 void MCAsmStreamer::EmitELFSize(MCSymbol
*Symbol
, const MCExpr
*Value
) {
346 assert(MAI
.hasDotTypeDotSizeDirective());
347 OS
<< "\t.size\t" << *Symbol
<< ", " << *Value
<< '\n';
350 void MCAsmStreamer::EmitCommonSymbol(MCSymbol
*Symbol
, uint64_t Size
,
351 unsigned ByteAlignment
) {
352 OS
<< "\t.comm\t" << *Symbol
<< ',' << Size
;
353 if (ByteAlignment
!= 0) {
354 if (MAI
.getCOMMDirectiveAlignmentIsInBytes())
355 OS
<< ',' << ByteAlignment
;
357 OS
<< ',' << Log2_32(ByteAlignment
);
362 /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
364 /// @param Symbol - The common symbol to emit.
365 /// @param Size - The size of the common symbol.
366 void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol
*Symbol
, uint64_t Size
) {
367 assert(MAI
.hasLCOMMDirective() && "Doesn't have .lcomm, can't emit it!");
368 OS
<< "\t.lcomm\t" << *Symbol
<< ',' << Size
;
372 void MCAsmStreamer::EmitZerofill(const MCSection
*Section
, MCSymbol
*Symbol
,
373 unsigned Size
, unsigned ByteAlignment
) {
374 // Note: a .zerofill directive does not switch sections.
377 // This is a mach-o specific directive.
378 const MCSectionMachO
*MOSection
= ((const MCSectionMachO
*)Section
);
379 OS
<< MOSection
->getSegmentName() << "," << MOSection
->getSectionName();
381 if (Symbol
!= NULL
) {
382 OS
<< ',' << *Symbol
<< ',' << Size
;
383 if (ByteAlignment
!= 0)
384 OS
<< ',' << Log2_32(ByteAlignment
);
389 // .tbss sym, size, align
390 // This depends that the symbol has already been mangled from the original,
392 void MCAsmStreamer::EmitTBSSSymbol(const MCSection
*Section
, MCSymbol
*Symbol
,
393 uint64_t Size
, unsigned ByteAlignment
) {
394 assert(Symbol
!= NULL
&& "Symbol shouldn't be NULL!");
395 // Instead of using the Section we'll just use the shortcut.
396 // This is a mach-o specific directive and section.
397 OS
<< ".tbss " << *Symbol
<< ", " << Size
;
399 // Output align if we have it. We default to 1 so don't bother printing
401 if (ByteAlignment
> 1) OS
<< ", " << Log2_32(ByteAlignment
);
406 static inline char toOctal(int X
) { return (X
&7)+'0'; }
408 static void PrintQuotedString(StringRef Data
, raw_ostream
&OS
) {
411 for (unsigned i
= 0, e
= Data
.size(); i
!= e
; ++i
) {
412 unsigned char C
= Data
[i
];
413 if (C
== '"' || C
== '\\') {
414 OS
<< '\\' << (char)C
;
418 if (isprint((unsigned char)C
)) {
424 case '\b': OS
<< "\\b"; break;
425 case '\f': OS
<< "\\f"; break;
426 case '\n': OS
<< "\\n"; break;
427 case '\r': OS
<< "\\r"; break;
428 case '\t': OS
<< "\\t"; break;
431 OS
<< toOctal(C
>> 6);
432 OS
<< toOctal(C
>> 3);
433 OS
<< toOctal(C
>> 0);
442 void MCAsmStreamer::EmitBytes(StringRef Data
, unsigned AddrSpace
) {
443 assert(CurSection
&& "Cannot emit contents before setting section!");
444 if (Data
.empty()) return;
446 if (Data
.size() == 1) {
447 OS
<< MAI
.getData8bitsDirective(AddrSpace
);
448 OS
<< (unsigned)(unsigned char)Data
[0];
453 // If the data ends with 0 and the target supports .asciz, use it, otherwise
455 if (MAI
.getAscizDirective() && Data
.back() == 0) {
456 OS
<< MAI
.getAscizDirective();
457 Data
= Data
.substr(0, Data
.size()-1);
459 OS
<< MAI
.getAsciiDirective();
463 PrintQuotedString(Data
, OS
);
467 /// EmitIntValue - Special case of EmitValue that avoids the client having
468 /// to pass in a MCExpr for constant integers.
469 void MCAsmStreamer::EmitIntValue(uint64_t Value
, unsigned Size
,
470 unsigned AddrSpace
) {
471 assert(CurSection
&& "Cannot emit contents before setting section!");
472 const char *Directive
= 0;
475 case 1: Directive
= MAI
.getData8bitsDirective(AddrSpace
); break;
476 case 2: Directive
= MAI
.getData16bitsDirective(AddrSpace
); break;
477 case 4: Directive
= MAI
.getData32bitsDirective(AddrSpace
); break;
479 Directive
= MAI
.getData64bitsDirective(AddrSpace
);
480 // If the target doesn't support 64-bit data, emit as two 32-bit halves.
481 if (Directive
) break;
482 if (isLittleEndian()) {
483 EmitIntValue((uint32_t)(Value
>> 0 ), 4, AddrSpace
);
484 EmitIntValue((uint32_t)(Value
>> 32), 4, AddrSpace
);
486 EmitIntValue((uint32_t)(Value
>> 32), 4, AddrSpace
);
487 EmitIntValue((uint32_t)(Value
>> 0 ), 4, AddrSpace
);
492 assert(Directive
&& "Invalid size for machine code value!");
493 OS
<< Directive
<< truncateToSize(Value
, Size
);
497 void MCAsmStreamer::EmitValue(const MCExpr
*Value
, unsigned Size
,
498 unsigned AddrSpace
) {
499 assert(CurSection
&& "Cannot emit contents before setting section!");
500 const char *Directive
= 0;
503 case 1: Directive
= MAI
.getData8bitsDirective(AddrSpace
); break;
504 case 2: Directive
= MAI
.getData16bitsDirective(AddrSpace
); break;
505 case 4: Directive
= MAI
.getData32bitsDirective(AddrSpace
); break;
506 case 8: Directive
= MAI
.getData64bitsDirective(AddrSpace
); break;
509 assert(Directive
&& "Invalid size for machine code value!");
510 OS
<< Directive
<< *Value
;
514 void MCAsmStreamer::EmitULEB128Value(const MCExpr
*Value
, unsigned AddrSpace
) {
515 OS
<< ".uleb " << *Value
;
519 void MCAsmStreamer::EmitSLEB128Value(const MCExpr
*Value
, unsigned AddrSpace
) {
520 OS
<< ".sleb " << *Value
;
524 void MCAsmStreamer::EmitGPRel32Value(const MCExpr
*Value
) {
525 assert(MAI
.getGPRel32Directive() != 0);
526 OS
<< MAI
.getGPRel32Directive() << *Value
;
531 /// EmitFill - Emit NumBytes bytes worth of the value specified by
532 /// FillValue. This implements directives such as '.space'.
533 void MCAsmStreamer::EmitFill(uint64_t NumBytes
, uint8_t FillValue
,
534 unsigned AddrSpace
) {
535 if (NumBytes
== 0) return;
538 if (const char *ZeroDirective
= MAI
.getZeroDirective()) {
539 OS
<< ZeroDirective
<< NumBytes
;
541 OS
<< ',' << (int)FillValue
;
546 // Emit a byte at a time.
547 MCStreamer::EmitFill(NumBytes
, FillValue
, AddrSpace
);
550 void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment
, int64_t Value
,
552 unsigned MaxBytesToEmit
) {
553 // Some assemblers don't support non-power of two alignments, so we always
554 // emit alignments as a power of two if possible.
555 if (isPowerOf2_32(ByteAlignment
)) {
557 default: llvm_unreachable("Invalid size for machine code value!");
558 case 1: OS
<< MAI
.getAlignDirective(); break;
559 // FIXME: use MAI for this!
560 case 2: OS
<< ".p2alignw "; break;
561 case 4: OS
<< ".p2alignl "; break;
562 case 8: llvm_unreachable("Unsupported alignment size!");
565 if (MAI
.getAlignmentIsInBytes())
568 OS
<< Log2_32(ByteAlignment
);
570 if (Value
|| MaxBytesToEmit
) {
572 OS
.write_hex(truncateToSize(Value
, ValueSize
));
575 OS
<< ", " << MaxBytesToEmit
;
581 // Non-power of two alignment. This is not widely supported by assemblers.
582 // FIXME: Parameterize this based on MAI.
584 default: llvm_unreachable("Invalid size for machine code value!");
585 case 1: OS
<< ".balign"; break;
586 case 2: OS
<< ".balignw"; break;
587 case 4: OS
<< ".balignl"; break;
588 case 8: llvm_unreachable("Unsupported alignment size!");
591 OS
<< ' ' << ByteAlignment
;
592 OS
<< ", " << truncateToSize(Value
, ValueSize
);
594 OS
<< ", " << MaxBytesToEmit
;
598 void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment
,
599 unsigned MaxBytesToEmit
) {
600 // Emit with a text fill value.
601 EmitValueToAlignment(ByteAlignment
, MAI
.getTextAlignFillValue(),
605 void MCAsmStreamer::EmitValueToOffset(const MCExpr
*Offset
,
606 unsigned char Value
) {
607 // FIXME: Verify that Offset is associated with the current section.
608 OS
<< ".org " << *Offset
<< ", " << (unsigned) Value
;
613 void MCAsmStreamer::EmitFileDirective(StringRef Filename
) {
614 assert(MAI
.hasSingleParameterDotFile());
616 PrintQuotedString(Filename
, OS
);
620 void MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo
, StringRef Filename
){
621 OS
<< "\t.file\t" << FileNo
<< ' ';
622 PrintQuotedString(Filename
, OS
);
626 void MCAsmStreamer::AddEncodingComment(const MCInst
&Inst
) {
627 raw_ostream
&OS
= GetCommentOS();
628 SmallString
<256> Code
;
629 SmallVector
<MCFixup
, 4> Fixups
;
630 raw_svector_ostream
VecOS(Code
);
631 Emitter
->EncodeInstruction(Inst
, VecOS
, Fixups
);
634 // If we are showing fixups, create symbolic markers in the encoded
635 // representation. We do this by making a per-bit map to the fixup item index,
636 // then trying to display it as nicely as possible.
637 SmallVector
<uint8_t, 64> FixupMap
;
638 FixupMap
.resize(Code
.size() * 8);
639 for (unsigned i
= 0, e
= Code
.size() * 8; i
!= e
; ++i
)
642 for (unsigned i
= 0, e
= Fixups
.size(); i
!= e
; ++i
) {
643 MCFixup
&F
= Fixups
[i
];
644 const MCFixupKindInfo
&Info
= Emitter
->getFixupKindInfo(F
.getKind());
645 for (unsigned j
= 0; j
!= Info
.TargetSize
; ++j
) {
646 unsigned Index
= F
.getOffset() * 8 + Info
.TargetOffset
+ j
;
647 assert(Index
< Code
.size() * 8 && "Invalid offset in fixup!");
648 FixupMap
[Index
] = 1 + i
;
653 for (unsigned i
= 0, e
= Code
.size(); i
!= e
; ++i
) {
657 // See if all bits are the same map entry.
658 uint8_t MapEntry
= FixupMap
[i
* 8 + 0];
659 for (unsigned j
= 1; j
!= 8; ++j
) {
660 if (FixupMap
[i
* 8 + j
] == MapEntry
)
663 MapEntry
= uint8_t(~0U);
667 if (MapEntry
!= uint8_t(~0U)) {
669 OS
<< format("0x%02x", uint8_t(Code
[i
]));
671 assert(Code
[i
] == 0 && "Encoder wrote into fixed up bit!");
672 OS
<< char('A' + MapEntry
- 1);
675 // Otherwise, write out in binary.
677 for (unsigned j
= 8; j
--;) {
678 unsigned Bit
= (Code
[i
] >> j
) & 1;
679 if (uint8_t MapEntry
= FixupMap
[i
* 8 + j
]) {
680 assert(Bit
== 0 && "Encoder wrote into fixed up bit!");
681 OS
<< char('A' + MapEntry
- 1);
689 for (unsigned i
= 0, e
= Fixups
.size(); i
!= e
; ++i
) {
690 MCFixup
&F
= Fixups
[i
];
691 const MCFixupKindInfo
&Info
= Emitter
->getFixupKindInfo(F
.getKind());
692 OS
<< " fixup " << char('A' + i
) << " - " << "offset: " << F
.getOffset()
693 << ", value: " << *F
.getValue() << ", kind: " << Info
.Name
<< "\n";
697 void MCAsmStreamer::EmitInstruction(const MCInst
&Inst
) {
698 assert(CurSection
&& "Cannot emit contents before setting section!");
700 // Show the encoding in a comment if we have a code emitter.
702 AddEncodingComment(Inst
);
704 // Show the MCInst if enabled.
706 Inst
.dump_pretty(GetCommentOS(), &MAI
, InstPrinter
.get(), "\n ");
707 GetCommentOS() << "\n";
710 // If we have an AsmPrinter, use that to print, otherwise print the MCInst.
712 InstPrinter
->printInst(&Inst
, OS
);
714 Inst
.print(OS
, &MAI
);
718 /// EmitRawText - If this file is backed by an assembly streamer, this dumps
719 /// the specified string in the output .s file. This capability is
720 /// indicated by the hasRawTextSupport() predicate.
721 void MCAsmStreamer::EmitRawText(StringRef String
) {
722 if (!String
.empty() && String
.back() == '\n')
723 String
= String
.substr(0, String
.size()-1);
728 void MCAsmStreamer::Finish() {
731 MCStreamer
*llvm::createAsmStreamer(MCContext
&Context
,
732 formatted_raw_ostream
&OS
,
734 bool isVerboseAsm
, MCInstPrinter
*IP
,
735 MCCodeEmitter
*CE
, bool ShowInst
) {
736 return new MCAsmStreamer(Context
, OS
, isLittleEndian
, isVerboseAsm
,