OLD | NEW |
1 //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output --------------------===// | 1 //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output --------------------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 | 9 |
10 #include "llvm/MC/MCStreamer.h" | 10 #include "llvm/MC/MCStreamer.h" |
| 11 #include "llvm/MC/MCAsmStreamer.h" |
11 #include "llvm/ADT/STLExtras.h" | 12 #include "llvm/ADT/STLExtras.h" |
12 #include "llvm/ADT/SmallString.h" | 13 #include "llvm/ADT/SmallString.h" |
13 #include "llvm/ADT/StringExtras.h" | 14 #include "llvm/ADT/StringExtras.h" |
14 #include "llvm/ADT/Twine.h" | 15 #include "llvm/ADT/Twine.h" |
15 #include "llvm/MC/MCAsmBackend.h" | 16 #include "llvm/MC/MCAsmBackend.h" |
16 #include "llvm/MC/MCAsmInfo.h" | 17 #include "llvm/MC/MCAsmInfo.h" |
17 #include "llvm/MC/MCCodeEmitter.h" | 18 #include "llvm/MC/MCCodeEmitter.h" |
18 #include "llvm/MC/MCContext.h" | 19 #include "llvm/MC/MCContext.h" |
19 #include "llvm/MC/MCExpr.h" | 20 #include "llvm/MC/MCExpr.h" |
20 #include "llvm/MC/MCFixupKindInfo.h" | 21 #include "llvm/MC/MCFixupKindInfo.h" |
21 #include "llvm/MC/MCInst.h" | 22 #include "llvm/MC/MCInst.h" |
22 #include "llvm/MC/MCInstPrinter.h" | 23 #include "llvm/MC/MCInstPrinter.h" |
23 #include "llvm/MC/MCObjectFileInfo.h" | 24 #include "llvm/MC/MCObjectFileInfo.h" |
24 #include "llvm/MC/MCRegisterInfo.h" | 25 #include "llvm/MC/MCRegisterInfo.h" |
25 #include "llvm/MC/MCSectionCOFF.h" | 26 #include "llvm/MC/MCSectionCOFF.h" |
26 #include "llvm/MC/MCSectionMachO.h" | 27 #include "llvm/MC/MCSectionMachO.h" |
27 #include "llvm/MC/MCSymbol.h" | 28 #include "llvm/MC/MCSymbol.h" |
28 #include "llvm/Support/CommandLine.h" | 29 #include "llvm/Support/CommandLine.h" |
29 #include "llvm/Support/ErrorHandling.h" | 30 #include "llvm/Support/ErrorHandling.h" |
30 #include "llvm/Support/Format.h" | 31 #include "llvm/Support/Format.h" |
31 #include "llvm/Support/FormattedStream.h" | 32 #include "llvm/Support/FormattedStream.h" |
32 #include "llvm/Support/MathExtras.h" | 33 #include "llvm/Support/MathExtras.h" |
33 #include "llvm/Support/Path.h" | 34 #include "llvm/Support/Path.h" |
34 #include <cctype> | 35 #include <cctype> |
35 using namespace llvm; | 36 using namespace llvm; |
36 | 37 |
37 namespace { | |
38 | |
39 class MCAsmStreamer final : public MCStreamer { | |
40 std::unique_ptr<formatted_raw_ostream> OSOwner; | |
41 formatted_raw_ostream &OS; | |
42 const MCAsmInfo *MAI; | |
43 std::unique_ptr<MCInstPrinter> InstPrinter; | |
44 std::unique_ptr<MCCodeEmitter> Emitter; | |
45 std::unique_ptr<MCAsmBackend> AsmBackend; | |
46 | |
47 SmallString<128> CommentToEmit; | |
48 raw_svector_ostream CommentStream; | |
49 | |
50 unsigned IsVerboseAsm : 1; | |
51 unsigned ShowInst : 1; | |
52 unsigned UseDwarfDirectory : 1; | |
53 // @LOCALMOD: we don't have an MCAssembler object here, so we can't ask it | |
54 // if bundle alignment is enabled. Instead, just track the alignment here. | |
55 unsigned BundleAlignmentEnabled : 1; | |
56 | |
57 void EmitRegisterName(int64_t Register); | |
58 void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; | |
59 void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; | |
60 | |
61 public: | |
62 MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os, | |
63 bool isVerboseAsm, bool useDwarfDirectory, | |
64 MCInstPrinter *printer, MCCodeEmitter *emitter, | |
65 MCAsmBackend *asmbackend, bool showInst) | |
66 : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner), | |
67 MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter), | |
68 AsmBackend(asmbackend), CommentStream(CommentToEmit), | |
69 IsVerboseAsm(isVerboseAsm), ShowInst(showInst), | |
70 UseDwarfDirectory(useDwarfDirectory), | |
71 BundleAlignmentEnabled(0) { | |
72 if (InstPrinter && IsVerboseAsm) | |
73 InstPrinter->setCommentStream(CommentStream); | |
74 } | |
75 | |
76 inline void EmitEOL() { | |
77 // If we don't have any comments, just emit a \n. | |
78 if (!IsVerboseAsm) { | |
79 OS << '\n'; | |
80 return; | |
81 } | |
82 EmitCommentsAndEOL(); | |
83 } | |
84 void EmitCommentsAndEOL(); | |
85 | |
86 /// isVerboseAsm - Return true if this streamer supports verbose assembly at | |
87 /// all. | |
88 bool isVerboseAsm() const override { return IsVerboseAsm; } | |
89 | |
90 /// hasRawTextSupport - We support EmitRawText. | |
91 bool hasRawTextSupport() const override { return true; } | |
92 | |
93 /// AddComment - Add a comment that can be emitted to the generated .s | |
94 /// file if applicable as a QoI issue to make the output of the compiler | |
95 /// more readable. This only affects the MCAsmStreamer, and only when | |
96 /// verbose assembly output is enabled. | |
97 void AddComment(const Twine &T) override; | |
98 | |
99 /// AddEncodingComment - Add a comment showing the encoding of an instruction. | |
100 void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &); | |
101 | |
102 /// GetCommentOS - Return a raw_ostream that comments can be written to. | |
103 /// Unlike AddComment, you are required to terminate comments with \n if you | |
104 /// use this method. | |
105 raw_ostream &GetCommentOS() override { | |
106 if (!IsVerboseAsm) | |
107 return nulls(); // Discard comments unless in verbose asm mode. | |
108 return CommentStream; | |
109 } | |
110 | |
111 void emitRawComment(const Twine &T, bool TabPrefix = true) override; | |
112 | |
113 /// AddBlankLine - Emit a blank line to a .s file to pretty it up. | |
114 void AddBlankLine() override { | |
115 EmitEOL(); | |
116 } | |
117 | |
118 /// @name MCStreamer Interface | |
119 /// @{ | |
120 | |
121 void ChangeSection(const MCSection *Section, | |
122 const MCExpr *Subsection) override; | |
123 | |
124 void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override; | |
125 void EmitLabel(MCSymbol *Symbol) override; | |
126 | |
127 void EmitAssemblerFlag(MCAssemblerFlag Flag) override; | |
128 void EmitLinkerOptions(ArrayRef<std::string> Options) override; | |
129 void EmitDataRegion(MCDataRegionType Kind) override; | |
130 void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, | |
131 unsigned Update) override; | |
132 void EmitThumbFunc(MCSymbol *Func) override; | |
133 | |
134 void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; | |
135 void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; | |
136 bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; | |
137 | |
138 void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; | |
139 void BeginCOFFSymbolDef(const MCSymbol *Symbol) override; | |
140 void EmitCOFFSymbolStorageClass(int StorageClass) override; | |
141 void EmitCOFFSymbolType(int Type) override; | |
142 void EndCOFFSymbolDef() override; | |
143 void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; | |
144 void EmitCOFFSecRel32(MCSymbol const *Symbol) override; | |
145 void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; | |
146 void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, | |
147 unsigned ByteAlignment) override; | |
148 | |
149 /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. | |
150 /// | |
151 /// @param Symbol - The common symbol to emit. | |
152 /// @param Size - The size of the common symbol. | |
153 /// @param ByteAlignment - The alignment of the common symbol in bytes. | |
154 void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, | |
155 unsigned ByteAlignment) override; | |
156 | |
157 void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, | |
158 uint64_t Size = 0, unsigned ByteAlignment = 0) override; | |
159 | |
160 void EmitTBSSSymbol (const MCSection *Section, MCSymbol *Symbol, | |
161 uint64_t Size, unsigned ByteAlignment = 0) override; | |
162 | |
163 void EmitBytes(StringRef Data) override; | |
164 | |
165 void EmitValueImpl(const MCExpr *Value, unsigned Size, | |
166 const SMLoc &Loc = SMLoc()) override; | |
167 void EmitIntValue(uint64_t Value, unsigned Size) override; | |
168 | |
169 void EmitULEB128Value(const MCExpr *Value) override; | |
170 | |
171 void EmitSLEB128Value(const MCExpr *Value) override; | |
172 | |
173 void EmitGPRel64Value(const MCExpr *Value) override; | |
174 | |
175 void EmitGPRel32Value(const MCExpr *Value) override; | |
176 | |
177 | |
178 void EmitFill(uint64_t NumBytes, uint8_t FillValue) override; | |
179 | |
180 void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, | |
181 unsigned ValueSize = 1, | |
182 unsigned MaxBytesToEmit = 0) override; | |
183 | |
184 void EmitCodeAlignment(unsigned ByteAlignment, | |
185 unsigned MaxBytesToEmit = 0) override; | |
186 | |
187 bool EmitValueToOffset(const MCExpr *Offset, | |
188 unsigned char Value = 0) override; | |
189 | |
190 void EmitFileDirective(StringRef Filename) override; | |
191 unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, | |
192 StringRef Filename, | |
193 unsigned CUID = 0) override; | |
194 void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, | |
195 unsigned Column, unsigned Flags, | |
196 unsigned Isa, unsigned Discriminator, | |
197 StringRef FileName) override; | |
198 MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override; | |
199 | |
200 void EmitIdent(StringRef IdentString) override; | |
201 void EmitCFISections(bool EH, bool Debug) override; | |
202 void EmitCFIDefCfa(int64_t Register, int64_t Offset) override; | |
203 void EmitCFIDefCfaOffset(int64_t Offset) override; | |
204 void EmitCFIDefCfaRegister(int64_t Register) override; | |
205 void EmitCFIOffset(int64_t Register, int64_t Offset) override; | |
206 void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override; | |
207 void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override; | |
208 void EmitCFIRememberState() override; | |
209 void EmitCFIRestoreState() override; | |
210 void EmitCFISameValue(int64_t Register) override; | |
211 void EmitCFIRelOffset(int64_t Register, int64_t Offset) override; | |
212 void EmitCFIAdjustCfaOffset(int64_t Adjustment) override; | |
213 void EmitCFISignalFrame() override; | |
214 void EmitCFIUndefined(int64_t Register) override; | |
215 void EmitCFIRegister(int64_t Register1, int64_t Register2) override; | |
216 void EmitCFIWindowSave() override; | |
217 | |
218 void EmitWinCFIStartProc(const MCSymbol *Symbol) override; | |
219 void EmitWinCFIEndProc() override; | |
220 void EmitWinCFIStartChained() override; | |
221 void EmitWinCFIEndChained() override; | |
222 void EmitWinCFIPushReg(unsigned Register) override; | |
223 void EmitWinCFISetFrame(unsigned Register, unsigned Offset) override; | |
224 void EmitWinCFIAllocStack(unsigned Size) override; | |
225 void EmitWinCFISaveReg(unsigned Register, unsigned Offset) override; | |
226 void EmitWinCFISaveXMM(unsigned Register, unsigned Offset) override; | |
227 void EmitWinCFIPushFrame(bool Code) override; | |
228 void EmitWinCFIEndProlog() override; | |
229 | |
230 void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override; | |
231 void EmitWinEHHandlerData() override; | |
232 | |
233 void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; | |
234 | |
235 void EmitBundleAlignMode(unsigned AlignPow2) override; | |
236 void EmitBundleLock(bool AlignToEnd) override; | |
237 void EmitBundleUnlock() override; | |
238 | |
239 /// EmitRawText - If this file is backed by an assembly streamer, this dumps | |
240 /// the specified string in the output .s file. This capability is | |
241 /// indicated by the hasRawTextSupport() predicate. | |
242 void EmitRawTextImpl(StringRef String) override; | |
243 | |
244 void FinishImpl() override; | |
245 }; | |
246 | |
247 } // end anonymous namespace. | |
248 | |
249 /// AddComment - Add a comment that can be emitted to the generated .s | 38 /// AddComment - Add a comment that can be emitted to the generated .s |
250 /// file if applicable as a QoI issue to make the output of the compiler | 39 /// file if applicable as a QoI issue to make the output of the compiler |
251 /// more readable. This only affects the MCAsmStreamer, and only when | 40 /// more readable. This only affects the MCAsmStreamer, and only when |
252 /// verbose assembly output is enabled. | 41 /// verbose assembly output is enabled. |
253 void MCAsmStreamer::AddComment(const Twine &T) { | 42 void MCAsmStreamer::AddComment(const Twine &T) { |
254 if (!IsVerboseAsm) return; | 43 if (!IsVerboseAsm) return; |
255 | 44 |
256 // Make sure that CommentStream is flushed. | 45 // Make sure that CommentStream is flushed. |
257 CommentStream.flush(); | 46 CommentStream.flush(); |
258 | 47 |
(...skipping 988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1247 const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); | 1036 const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); |
1248 OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() | 1037 OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() |
1249 << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; | 1038 << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; |
1250 } | 1039 } |
1251 } | 1040 } |
1252 | 1041 |
1253 void MCAsmStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &S
TI) { | 1042 void MCAsmStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &S
TI) { |
1254 assert(getCurrentSection().first && | 1043 assert(getCurrentSection().first && |
1255 "Cannot emit contents before setting section!"); | 1044 "Cannot emit contents before setting section!"); |
1256 | 1045 |
1257 // @LOCALMOD-START | |
1258 if (BundleAlignmentEnabled && AsmBackend && | |
1259 AsmBackend->CustomExpandInst(Inst, *this)) { | |
1260 return; | |
1261 } | |
1262 // @LOCALMOD-END | |
1263 // Show the encoding in a comment if we have a code emitter. | |
1264 if (Emitter) | 1046 if (Emitter) |
1265 AddEncodingComment(Inst, STI); | 1047 AddEncodingComment(Inst, STI); |
1266 | 1048 |
1267 // Show the MCInst if enabled. | 1049 // Show the MCInst if enabled. |
1268 if (ShowInst) { | 1050 if (ShowInst) { |
1269 Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n "); | 1051 Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n "); |
1270 GetCommentOS() << "\n"; | 1052 GetCommentOS() << "\n"; |
1271 } | 1053 } |
1272 | 1054 |
1273 // If we have an AsmPrinter, use that to print, otherwise print the MCInst. | 1055 // If we have an AsmPrinter, use that to print, otherwise print the MCInst. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1325 } | 1107 } |
1326 | 1108 |
1327 MCStreamer *llvm::createAsmStreamer(MCContext &Context, | 1109 MCStreamer *llvm::createAsmStreamer(MCContext &Context, |
1328 std::unique_ptr<formatted_raw_ostream> OS, | 1110 std::unique_ptr<formatted_raw_ostream> OS, |
1329 bool isVerboseAsm, bool useDwarfDirectory, | 1111 bool isVerboseAsm, bool useDwarfDirectory, |
1330 MCInstPrinter *IP, MCCodeEmitter *CE, | 1112 MCInstPrinter *IP, MCCodeEmitter *CE, |
1331 MCAsmBackend *MAB, bool ShowInst) { | 1113 MCAsmBackend *MAB, bool ShowInst) { |
1332 return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm, | 1114 return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm, |
1333 useDwarfDirectory, IP, CE, MAB, ShowInst); | 1115 useDwarfDirectory, IP, CE, MAB, ShowInst); |
1334 } | 1116 } |
OLD | NEW |