Bug Summary

File:src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/MC/MCAsmStreamer.cpp
Warning:line 1248, column 28
The result of the right shift is undefined due to shifting by '64', which is greater or equal to the width of type 'unsigned long long'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name MCAsmStreamer.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Analysis -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ASMParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/BinaryFormat -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitstream -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /include/llvm/CodeGen -I /include/llvm/CodeGen/PBQP -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Coroutines -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData/Coverage -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/CodeView -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/DWARF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/MSF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/PDB -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Demangle -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/JITLink -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/Orc -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenACC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenMP -I /include/llvm/CodeGen/GlobalISel -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IRReader -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/LTO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Linker -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC/MCParser -I /include/llvm/CodeGen/MIRParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Object -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Option -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Passes -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Scalar -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ADT -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/Symbolize -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Target -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Utils -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Vectorize -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/IPO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libLLVM/../include -I /usr/src/gnu/usr.bin/clang/libLLVM/obj -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -D PIC -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -D_RET_PROTECTOR -ret-protector -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/MC/MCAsmStreamer.cpp
1//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ADT/Optional.h"
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/SmallString.h"
12#include "llvm/ADT/StringExtras.h"
13#include "llvm/ADT/Twine.h"
14#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
15#include "llvm/MC/MCAsmBackend.h"
16#include "llvm/MC/MCAsmInfo.h"
17#include "llvm/MC/MCAssembler.h"
18#include "llvm/MC/MCCodeEmitter.h"
19#include "llvm/MC/MCCodeView.h"
20#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCExpr.h"
22#include "llvm/MC/MCFixupKindInfo.h"
23#include "llvm/MC/MCInst.h"
24#include "llvm/MC/MCInstPrinter.h"
25#include "llvm/MC/MCObjectFileInfo.h"
26#include "llvm/MC/MCObjectWriter.h"
27#include "llvm/MC/MCPseudoProbe.h"
28#include "llvm/MC/MCRegister.h"
29#include "llvm/MC/MCRegisterInfo.h"
30#include "llvm/MC/MCSectionMachO.h"
31#include "llvm/MC/MCStreamer.h"
32#include "llvm/MC/MCSymbolXCOFF.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/Format.h"
35#include "llvm/Support/FormattedStream.h"
36#include "llvm/Support/LEB128.h"
37#include "llvm/Support/MathExtras.h"
38#include "llvm/Support/Path.h"
39#include "llvm/Support/TargetRegistry.h"
40#include <cctype>
41
42using namespace llvm;
43
44namespace {
45
46class MCAsmStreamer final : public MCStreamer {
47 std::unique_ptr<formatted_raw_ostream> OSOwner;
48 formatted_raw_ostream &OS;
49 const MCAsmInfo *MAI;
50 std::unique_ptr<MCInstPrinter> InstPrinter;
51 std::unique_ptr<MCAssembler> Assembler;
52
53 SmallString<128> ExplicitCommentToEmit;
54 SmallString<128> CommentToEmit;
55 raw_svector_ostream CommentStream;
56 raw_null_ostream NullStream;
57
58 unsigned IsVerboseAsm : 1;
59 unsigned ShowInst : 1;
60 unsigned UseDwarfDirectory : 1;
61
62 void EmitRegisterName(int64_t Register);
63 void PrintQuotedString(StringRef Data, raw_ostream &OS) const;
64 void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
65 StringRef Filename,
66 Optional<MD5::MD5Result> Checksum,
67 Optional<StringRef> Source,
68 bool UseDwarfDirectory,
69 raw_svector_ostream &OS) const;
70 void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
71 void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
72
73public:
74 MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
75 bool isVerboseAsm, bool useDwarfDirectory,
76 MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,
77 std::unique_ptr<MCAsmBackend> asmbackend, bool showInst)
78 : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
79 MAI(Context.getAsmInfo()), InstPrinter(printer),
80 Assembler(std::make_unique<MCAssembler>(
81 Context, std::move(asmbackend), std::move(emitter),
82 (asmbackend) ? asmbackend->createObjectWriter(NullStream)
83 : nullptr)),
84 CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
85 ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
86 assert(InstPrinter)((void)0);
87 if (IsVerboseAsm)
88 InstPrinter->setCommentStream(CommentStream);
89 if (Assembler->getBackendPtr())
90 setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
91
92 Context.setUseNamesOnTempLabels(true);
93 }
94
95 MCAssembler &getAssembler() { return *Assembler; }
96 MCAssembler *getAssemblerPtr() override { return nullptr; }
97
98 inline void EmitEOL() {
99 // Dump Explicit Comments here.
100 emitExplicitComments();
101 // If we don't have any comments, just emit a \n.
102 if (!IsVerboseAsm) {
103 OS << '\n';
104 return;
105 }
106 EmitCommentsAndEOL();
107 }
108
109 void emitSyntaxDirective() override;
110
111 void EmitCommentsAndEOL();
112
113 /// Return true if this streamer supports verbose assembly at all.
114 bool isVerboseAsm() const override { return IsVerboseAsm; }
115
116 /// Do we support EmitRawText?
117 bool hasRawTextSupport() const override { return true; }
118
119 /// Add a comment that can be emitted to the generated .s file to make the
120 /// output of the compiler more readable. This only affects the MCAsmStreamer
121 /// and only when verbose assembly output is enabled.
122 void AddComment(const Twine &T, bool EOL = true) override;
123
124 /// Add a comment showing the encoding of an instruction.
125 void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);
126
127 /// Return a raw_ostream that comments can be written to.
128 /// Unlike AddComment, you are required to terminate comments with \n if you
129 /// use this method.
130 raw_ostream &GetCommentOS() override {
131 if (!IsVerboseAsm)
132 return nulls(); // Discard comments unless in verbose asm mode.
133 return CommentStream;
134 }
135
136 void emitRawComment(const Twine &T, bool TabPrefix = true) override;
137
138 void addExplicitComment(const Twine &T) override;
139 void emitExplicitComments() override;
140
141 /// Emit a blank line to a .s file to pretty it up.
142 void AddBlankLine() override {
143 EmitEOL();
144 }
145
146 /// @name MCStreamer Interface
147 /// @{
148
149 void changeSection(MCSection *Section, const MCExpr *Subsection) override;
150
151 void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name,
152 bool KeepOriginalSym) override;
153
154 void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
155
156 void emitGNUAttribute(unsigned Tag, unsigned Value) override;
157
158 StringRef getMnemonic(MCInst &MI) override {
159 return InstPrinter->getMnemonic(&MI).first;
160 }
161
162 void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
163
164 void emitAssemblerFlag(MCAssemblerFlag Flag) override;
165 void emitLinkerOptions(ArrayRef<std::string> Options) override;
166 void emitDataRegion(MCDataRegionType Kind) override;
167 void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
168 unsigned Update, VersionTuple SDKVersion) override;
169 void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
170 unsigned Update, VersionTuple SDKVersion) override;
171 void emitThumbFunc(MCSymbol *Func) override;
172
173 void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
174 void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
175 bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
176
177 void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
178 void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
179 void EmitCOFFSymbolStorageClass(int StorageClass) override;
180 void EmitCOFFSymbolType(int Type) override;
181 void EndCOFFSymbolDef() override;
182 void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
183 void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
184 void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
185 void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
186 void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
187 void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
188 MCSymbol *CsectSym,
189 unsigned ByteAlign) override;
190 void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
191 MCSymbolAttr Linakge,
192 MCSymbolAttr Visibility) override;
193 void emitXCOFFRenameDirective(const MCSymbol *Name,
194 StringRef Rename) override;
195
196 void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
197 void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
198 unsigned ByteAlignment) override;
199
200 /// Emit a local common (.lcomm) symbol.
201 ///
202 /// @param Symbol - The common symbol to emit.
203 /// @param Size - The size of the common symbol.
204 /// @param ByteAlignment - The alignment of the common symbol in bytes.
205 void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
206 unsigned ByteAlignment) override;
207
208 void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
209 uint64_t Size = 0, unsigned ByteAlignment = 0,
210 SMLoc Loc = SMLoc()) override;
211
212 void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
213 unsigned ByteAlignment = 0) override;
214
215 void emitBinaryData(StringRef Data) override;
216
217 void emitBytes(StringRef Data) override;
218
219 void emitValueImpl(const MCExpr *Value, unsigned Size,
220 SMLoc Loc = SMLoc()) override;
221 void emitIntValue(uint64_t Value, unsigned Size) override;
222 void emitIntValueInHex(uint64_t Value, unsigned Size) override;
223 void emitIntValueInHexWithPadding(uint64_t Value, unsigned Size) override;
224
225 void emitULEB128Value(const MCExpr *Value) override;
226
227 void emitSLEB128Value(const MCExpr *Value) override;
228
229 void emitDTPRel32Value(const MCExpr *Value) override;
230 void emitDTPRel64Value(const MCExpr *Value) override;
231 void emitTPRel32Value(const MCExpr *Value) override;
232 void emitTPRel64Value(const MCExpr *Value) override;
233
234 void emitGPRel64Value(const MCExpr *Value) override;
235
236 void emitGPRel32Value(const MCExpr *Value) override;
237
238 void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
239 SMLoc Loc = SMLoc()) override;
240
241 void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
242 SMLoc Loc = SMLoc()) override;
243
244 void emitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
245 unsigned ValueSize = 1,
246 unsigned MaxBytesToEmit = 0) override;
247
248 void emitCodeAlignment(unsigned ByteAlignment,
249 unsigned MaxBytesToEmit = 0) override;
250
251 void emitValueToOffset(const MCExpr *Offset,
252 unsigned char Value,
253 SMLoc Loc) override;
254
255 void emitFileDirective(StringRef Filename) override;
256 void emitFileDirective(StringRef Filename, StringRef CompilerVerion,
257 StringRef TimeStamp, StringRef Description) override;
258 Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo,
259 StringRef Directory,
260 StringRef Filename,
261 Optional<MD5::MD5Result> Checksum = None,
262 Optional<StringRef> Source = None,
263 unsigned CUID = 0) override;
264 void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
265 Optional<MD5::MD5Result> Checksum,
266 Optional<StringRef> Source,
267 unsigned CUID = 0) override;
268 void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
269 unsigned Flags, unsigned Isa,
270 unsigned Discriminator,
271 StringRef FileName) override;
272 MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
273
274 bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
275 ArrayRef<uint8_t> Checksum,
276 unsigned ChecksumKind) override;
277 bool EmitCVFuncIdDirective(unsigned FuncId) override;
278 bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
279 unsigned IAFile, unsigned IALine,
280 unsigned IACol, SMLoc Loc) override;
281 void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
282 unsigned Column, bool PrologueEnd, bool IsStmt,
283 StringRef FileName, SMLoc Loc) override;
284 void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
285 const MCSymbol *FnEnd) override;
286 void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
287 unsigned SourceFileId,
288 unsigned SourceLineNum,
289 const MCSymbol *FnStartSym,
290 const MCSymbol *FnEndSym) override;
291
292 void PrintCVDefRangePrefix(
293 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);
294
295 void emitCVDefRangeDirective(
296 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
297 codeview::DefRangeRegisterRelHeader DRHdr) override;
298
299 void emitCVDefRangeDirective(
300 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
301 codeview::DefRangeSubfieldRegisterHeader DRHdr) override;
302
303 void emitCVDefRangeDirective(
304 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
305 codeview::DefRangeRegisterHeader DRHdr) override;
306
307 void emitCVDefRangeDirective(
308 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
309 codeview::DefRangeFramePointerRelHeader DRHdr) override;
310
311 void emitCVStringTableDirective() override;
312 void emitCVFileChecksumsDirective() override;
313 void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
314 void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
315
316 void emitIdent(StringRef IdentString) override;
317 void emitCFIBKeyFrame() override;
318 void emitCFISections(bool EH, bool Debug) override;
319 void emitCFIDefCfa(int64_t Register, int64_t Offset) override;
320 void emitCFIDefCfaOffset(int64_t Offset) override;
321 void emitCFIDefCfaRegister(int64_t Register) override;
322 void emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,
323 int64_t AddressSpace) override;
324 void emitCFIOffset(int64_t Register, int64_t Offset) override;
325 void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
326 void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
327 void emitCFIRememberState() override;
328 void emitCFIRestoreState() override;
329 void emitCFIRestore(int64_t Register) override;
330 void emitCFISameValue(int64_t Register) override;
331 void emitCFIRelOffset(int64_t Register, int64_t Offset) override;
332 void emitCFIAdjustCfaOffset(int64_t Adjustment) override;
333 void emitCFIEscape(StringRef Values) override;
334 void emitCFIGnuArgsSize(int64_t Size) override;
335 void emitCFISignalFrame() override;
336 void emitCFIUndefined(int64_t Register) override;
337 void emitCFIRegister(int64_t Register1, int64_t Register2) override;
338 void emitCFIWindowSave() override;
339 void emitCFINegateRAState() override;
340 void emitCFIReturnColumn(int64_t Register) override;
341
342 void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
343 void EmitWinCFIEndProc(SMLoc Loc) override;
344 void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
345 void EmitWinCFIStartChained(SMLoc Loc) override;
346 void EmitWinCFIEndChained(SMLoc Loc) override;
347 void EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) override;
348 void EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
349 SMLoc Loc) override;
350 void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
351 void EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
352 SMLoc Loc) override;
353 void EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
354 SMLoc Loc) override;
355 void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override;
356 void EmitWinCFIEndProlog(SMLoc Loc) override;
357
358 void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
359 SMLoc Loc) override;
360 void EmitWinEHHandlerData(SMLoc Loc) override;
361
362 void emitCGProfileEntry(const MCSymbolRefExpr *From,
363 const MCSymbolRefExpr *To, uint64_t Count) override;
364
365 void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
366
367 void emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type,
368 uint64_t Attr,
369 const MCPseudoProbeInlineStack &InlineStack) override;
370
371 void emitBundleAlignMode(unsigned AlignPow2) override;
372 void emitBundleLock(bool AlignToEnd) override;
373 void emitBundleUnlock() override;
374
375 Optional<std::pair<bool, std::string>>
376 emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
377 SMLoc Loc, const MCSubtargetInfo &STI) override;
378
379 void emitAddrsig() override;
380 void emitAddrsigSym(const MCSymbol *Sym) override;
381
382 /// If this file is backed by an assembly streamer, this dumps the specified
383 /// string in the output .s file. This capability is indicated by the
384 /// hasRawTextSupport() predicate.
385 void emitRawTextImpl(StringRef String) override;
386
387 void finishImpl() override;
388
389 void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) override;
390
391 MCSymbol *emitDwarfUnitLength(const Twine &Prefix,
392 const Twine &Comment) override;
393
394 void emitDwarfLineStartLabel(MCSymbol *StartSym) override;
395
396 void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) override;
397
398 void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel,
399 const MCSymbol *Label,
400 unsigned PointerSize) override;
401
402 void doFinalizationAtSectionEnd(MCSection *Section) override;
403};
404
405} // end anonymous namespace.
406
407void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
408 if (!IsVerboseAsm) return;
409
410 T.toVector(CommentToEmit);
411
412 if (EOL)
413 CommentToEmit.push_back('\n'); // Place comment in a new line.
414}
415
416void MCAsmStreamer::EmitCommentsAndEOL() {
417 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
418 OS << '\n';
419 return;
420 }
421
422 StringRef Comments = CommentToEmit;
423
424 assert(Comments.back() == '\n' &&((void)0)
425 "Comment array not newline terminated")((void)0);
426 do {
427 // Emit a line of comments.
428 OS.PadToColumn(MAI->getCommentColumn());
429 size_t Position = Comments.find('\n');
430 OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
431
432 Comments = Comments.substr(Position+1);
433 } while (!Comments.empty());
434
435 CommentToEmit.clear();
436}
437
438static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
439 assert(Bytes > 0 && Bytes <= 8 && "Invalid size!")((void)0);
440 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
441}
442
443void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
444 if (TabPrefix)
445 OS << '\t';
446 OS << MAI->getCommentString() << T;
447 EmitEOL();
448}
449
450void MCAsmStreamer::addExplicitComment(const Twine &T) {
451 StringRef c = T.getSingleStringRef();
452 if (c.equals(StringRef(MAI->getSeparatorString())))
453 return;
454 if (c.startswith(StringRef("//"))) {
455 ExplicitCommentToEmit.append("\t");
456 ExplicitCommentToEmit.append(MAI->getCommentString());
457 // drop //
458 ExplicitCommentToEmit.append(c.slice(2, c.size()).str());
459 } else if (c.startswith(StringRef("/*"))) {
460 size_t p = 2, len = c.size() - 2;
461 // emit each line in comment as separate newline.
462 do {
463 size_t newp = std::min(len, c.find_first_of("\r\n", p));
464 ExplicitCommentToEmit.append("\t");
465 ExplicitCommentToEmit.append(MAI->getCommentString());
466 ExplicitCommentToEmit.append(c.slice(p, newp).str());
467 // If we have another line in this comment add line
468 if (newp < len)
469 ExplicitCommentToEmit.append("\n");
470 p = newp + 1;
471 } while (p < len);
472 } else if (c.startswith(StringRef(MAI->getCommentString()))) {
473 ExplicitCommentToEmit.append("\t");
474 ExplicitCommentToEmit.append(c.str());
475 } else if (c.front() == '#') {
476
477 ExplicitCommentToEmit.append("\t");
478 ExplicitCommentToEmit.append(MAI->getCommentString());
479 ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
480 } else
481 assert(false && "Unexpected Assembly Comment")((void)0);
482 // full line comments immediately output
483 if (c.back() == '\n')
484 emitExplicitComments();
485}
486
487void MCAsmStreamer::emitExplicitComments() {
488 StringRef Comments = ExplicitCommentToEmit;
489 if (!Comments.empty())
490 OS << Comments;
491 ExplicitCommentToEmit.clear();
492}
493
494void MCAsmStreamer::changeSection(MCSection *Section,
495 const MCExpr *Subsection) {
496 assert(Section && "Cannot switch to a null section!")((void)0);
497 if (MCTargetStreamer *TS = getTargetStreamer()) {
498 TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS);
499 } else {
500 Section->PrintSwitchToSection(*MAI, getContext().getTargetTriple(), OS,
501 Subsection);
502 }
503}
504
505void MCAsmStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
506 StringRef Name,
507 bool KeepOriginalSym) {
508 OS << ".symver ";
509 OriginalSym->print(OS, MAI);
510 OS << ", " << Name;
511 if (!KeepOriginalSym && !Name.contains("@@@"))
512 OS << ", remove";
513 EmitEOL();
514}
515
516void MCAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
517 MCStreamer::emitLabel(Symbol, Loc);
518
519 Symbol->print(OS, MAI);
520 OS << MAI->getLabelSuffix();
521
522 EmitEOL();
523}
524
525void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
526 StringRef str = MCLOHIdToName(Kind);
527
528#ifndef NDEBUG1
529 int NbArgs = MCLOHIdToNbArgs(Kind);
530 assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!")((void)0);
531 assert(str != "" && "Invalid LOH name")((void)0);
532#endif
533
534 OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
535 bool IsFirst = true;
536 for (const MCSymbol *Arg : Args) {
537 if (!IsFirst)
538 OS << ", ";
539 IsFirst = false;
540 Arg->print(OS, MAI);
541 }
542 EmitEOL();
543}
544
545void MCAsmStreamer::emitGNUAttribute(unsigned Tag, unsigned Value) {
546 OS << "\t.gnu_attribute " << Tag << ", " << Value << "\n";
547}
548
549void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
550 switch (Flag) {
551 case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;
552 case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
553 case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break;
554 case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break;
555 case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break;
556 }
557 EmitEOL();
558}
559
560void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
561 assert(!Options.empty() && "At least one option is required!")((void)0);
562 OS << "\t.linker_option \"" << Options[0] << '"';
563 for (ArrayRef<std::string>::iterator it = Options.begin() + 1,
564 ie = Options.end(); it != ie; ++it) {
565 OS << ", " << '"' << *it << '"';
566 }
567 EmitEOL();
568}
569
570void MCAsmStreamer::emitDataRegion(MCDataRegionType Kind) {
571 if (!MAI->doesSupportDataRegionDirectives())
572 return;
573 switch (Kind) {
574 case MCDR_DataRegion: OS << "\t.data_region"; break;
575 case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break;
576 case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break;
577 case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break;
578 case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break;
579 }
580 EmitEOL();
581}
582
583static const char *getVersionMinDirective(MCVersionMinType Type) {
584 switch (Type) {
585 case MCVM_WatchOSVersionMin: return ".watchos_version_min";
586 case MCVM_TvOSVersionMin: return ".tvos_version_min";
587 case MCVM_IOSVersionMin: return ".ios_version_min";
588 case MCVM_OSXVersionMin: return ".macosx_version_min";
589 }
590 llvm_unreachable("Invalid MC version min type")__builtin_unreachable();
591}
592
593static void EmitSDKVersionSuffix(raw_ostream &OS,
594 const VersionTuple &SDKVersion) {
595 if (SDKVersion.empty())
596 return;
597 OS << '\t' << "sdk_version " << SDKVersion.getMajor();
598 if (auto Minor = SDKVersion.getMinor()) {
599 OS << ", " << *Minor;
600 if (auto Subminor = SDKVersion.getSubminor()) {
601 OS << ", " << *Subminor;
602 }
603 }
604}
605
606void MCAsmStreamer::emitVersionMin(MCVersionMinType Type, unsigned Major,
607 unsigned Minor, unsigned Update,
608 VersionTuple SDKVersion) {
609 OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
610 if (Update)
611 OS << ", " << Update;
612 EmitSDKVersionSuffix(OS, SDKVersion);
613 EmitEOL();
614}
615
616static const char *getPlatformName(MachO::PlatformType Type) {
617 switch (Type) {
618 case MachO::PLATFORM_MACOS: return "macos";
619 case MachO::PLATFORM_IOS: return "ios";
620 case MachO::PLATFORM_TVOS: return "tvos";
621 case MachO::PLATFORM_WATCHOS: return "watchos";
622 case MachO::PLATFORM_BRIDGEOS: return "bridgeos";
623 case MachO::PLATFORM_MACCATALYST: return "macCatalyst";
624 case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator";
625 case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator";
626 case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
627 case MachO::PLATFORM_DRIVERKIT: return "driverkit";
628 }
629 llvm_unreachable("Invalid Mach-O platform type")__builtin_unreachable();
630}
631
632void MCAsmStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
633 unsigned Minor, unsigned Update,
634 VersionTuple SDKVersion) {
635 const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
636 OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
637 if (Update)
638 OS << ", " << Update;
639 EmitSDKVersionSuffix(OS, SDKVersion);
640 EmitEOL();
641}
642
643void MCAsmStreamer::emitThumbFunc(MCSymbol *Func) {
644 // This needs to emit to a temporary string to get properly quoted
645 // MCSymbols when they have spaces in them.
646 OS << "\t.thumb_func";
647 // Only Mach-O hasSubsectionsViaSymbols()
648 if (MAI->hasSubsectionsViaSymbols()) {
649 OS << '\t';
650 Func->print(OS, MAI);
651 }
652 EmitEOL();
653}
654
655void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
656 // Do not emit a .set on inlined target assignments.
657 bool EmitSet = true;
658 if (auto *E = dyn_cast<MCTargetExpr>(Value))
659 if (E->inlineAssignedExpr())
660 EmitSet = false;
661 if (EmitSet) {
662 OS << ".set ";
663 Symbol->print(OS, MAI);
664 OS << ", ";
665 Value->print(OS, MAI);
666
667 EmitEOL();
668 }
669
670 MCStreamer::emitAssignment(Symbol, Value);
671}
672
673void MCAsmStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
674 OS << ".weakref ";
675 Alias->print(OS, MAI);
676 OS << ", ";
677 Symbol->print(OS, MAI);
678 EmitEOL();
679}
680
681bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
682 MCSymbolAttr Attribute) {
683 switch (Attribute) {
684 case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute")__builtin_unreachable();
685 case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function
686 case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
687 case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object
688 case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object
689 case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common
690 case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype
691 case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object
692 if (!MAI->hasDotTypeDotSizeDirective())
693 return false; // Symbol attribute not supported
694 OS << "\t.type\t";
695 Symbol->print(OS, MAI);
696 OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
697 switch (Attribute) {
698 default: return false;
699 case MCSA_ELF_TypeFunction: OS << "function"; break;
700 case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
701 case MCSA_ELF_TypeObject: OS << "object"; break;
702 case MCSA_ELF_TypeTLS: OS << "tls_object"; break;
703 case MCSA_ELF_TypeCommon: OS << "common"; break;
704 case MCSA_ELF_TypeNoType: OS << "notype"; break;
705 case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
706 }
707 EmitEOL();
708 return true;
709 case MCSA_Global: // .globl/.global
710 OS << MAI->getGlobalDirective();
711 break;
712 case MCSA_LGlobal: OS << "\t.lglobl\t"; break;
713 case MCSA_Hidden: OS << "\t.hidden\t"; break;
714 case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
715 case MCSA_Internal: OS << "\t.internal\t"; break;
716 case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break;
717 case MCSA_Local: OS << "\t.local\t"; break;
718 case MCSA_NoDeadStrip:
719 if (!MAI->hasNoDeadStrip())
720 return false;
721 OS << "\t.no_dead_strip\t";
722 break;
723 case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
724 case MCSA_AltEntry: OS << "\t.alt_entry\t"; break;
725 case MCSA_PrivateExtern:
726 OS << "\t.private_extern\t";
727 break;
728 case MCSA_Protected: OS << "\t.protected\t"; break;
729 case MCSA_Reference: OS << "\t.reference\t"; break;
730 case MCSA_Extern:
731 OS << "\t.extern\t";
732 break;
733 case MCSA_Weak: OS << MAI->getWeakDirective(); break;
734 case MCSA_WeakDefinition:
735 OS << "\t.weak_definition\t";
736 break;
737 // .weak_reference
738 case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break;
739 case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
740 case MCSA_Cold:
741 // Assemblers currently do not support a .cold directive.
742 return false;
743 }
744
745 Symbol->print(OS, MAI);
746 EmitEOL();
747
748 return true;
749}
750
751void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
752 OS << ".desc" << ' ';
753 Symbol->print(OS, MAI);
754 OS << ',' << DescValue;
755 EmitEOL();
756}
757
758void MCAsmStreamer::emitSyntaxDirective() {
759 if (MAI->getAssemblerDialect() == 1) {
760 OS << "\t.intel_syntax noprefix";
761 EmitEOL();
762 }
763 // FIXME: Currently emit unprefix'ed registers.
764 // The intel_syntax directive has one optional argument
765 // with may have a value of prefix or noprefix.
766}
767
768void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
769 OS << "\t.def\t ";
770 Symbol->print(OS, MAI);
771 OS << ';';
772 EmitEOL();
773}
774
775void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) {
776 OS << "\t.scl\t" << StorageClass << ';';
777 EmitEOL();
778}
779
780void MCAsmStreamer::EmitCOFFSymbolType (int Type) {
781 OS << "\t.type\t" << Type << ';';
782 EmitEOL();
783}
784
785void MCAsmStreamer::EndCOFFSymbolDef() {
786 OS << "\t.endef";
787 EmitEOL();
788}
789
790void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
791 OS << "\t.safeseh\t";
792 Symbol->print(OS, MAI);
793 EmitEOL();
794}
795
796void MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
797 OS << "\t.symidx\t";
798 Symbol->print(OS, MAI);
799 EmitEOL();
800}
801
802void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
803 OS << "\t.secidx\t";
804 Symbol->print(OS, MAI);
805 EmitEOL();
806}
807
808void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
809 OS << "\t.secrel32\t";
810 Symbol->print(OS, MAI);
811 if (Offset != 0)
812 OS << '+' << Offset;
813 EmitEOL();
814}
815
816void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
817 OS << "\t.rva\t";
818 Symbol->print(OS, MAI);
819 if (Offset > 0)
820 OS << '+' << Offset;
821 else if (Offset < 0)
822 OS << '-' << -Offset;
823 EmitEOL();
824}
825
826// We need an XCOFF-specific version of this directive as the AIX syntax
827// requires a QualName argument identifying the csect name and storage mapping
828// class to appear before the alignment if we are specifying it.
829void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
830 uint64_t Size,
831 MCSymbol *CsectSym,
832 unsigned ByteAlignment) {
833 assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&((void)0)
834 "We only support writing log base-2 alignment format with XCOFF.")((void)0);
835 assert(isPowerOf2_32(ByteAlignment) && "Alignment must be a power of 2.")((void)0);
836
837 OS << "\t.lcomm\t";
838 LabelSym->print(OS, MAI);
839 OS << ',' << Size << ',';
840 CsectSym->print(OS, MAI);
841 OS << ',' << Log2_32(ByteAlignment);
842
843 EmitEOL();
844
845 // Print symbol's rename (original name contains invalid character(s)) if
846 // there is one.
847 MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(CsectSym);
848 if (XSym->hasRename())
849 emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
850}
851
852void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
853 MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
854
855 switch (Linkage) {
856 case MCSA_Global:
857 OS << MAI->getGlobalDirective();
858 break;
859 case MCSA_Weak:
860 OS << MAI->getWeakDirective();
861 break;
862 case MCSA_Extern:
863 OS << "\t.extern\t";
864 break;
865 case MCSA_LGlobal:
866 OS << "\t.lglobl\t";
867 break;
868 default:
869 report_fatal_error("unhandled linkage type");
870 }
871
872 Symbol->print(OS, MAI);
873
874 switch (Visibility) {
875 case MCSA_Invalid:
876 // Nothing to do.
877 break;
878 case MCSA_Hidden:
879 OS << ",hidden";
880 break;
881 case MCSA_Protected:
882 OS << ",protected";
883 break;
884 default:
885 report_fatal_error("unexpected value for Visibility type");
886 }
887 EmitEOL();
888
889 // Print symbol's rename (original name contains invalid character(s)) if
890 // there is one.
891 if (cast<MCSymbolXCOFF>(Symbol)->hasRename())
892 emitXCOFFRenameDirective(Symbol,
893 cast<MCSymbolXCOFF>(Symbol)->getSymbolTableName());
894}
895
896void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
897 StringRef Rename) {
898 OS << "\t.rename\t";
899 Name->print(OS, MAI);
900 const char DQ = '"';
901 OS << ',' << DQ;
902 for (char C : Rename) {
903 // To escape a double quote character, the character should be doubled.
904 if (C == DQ)
905 OS << DQ;
906 OS << C;
907 }
908 OS << DQ;
909 EmitEOL();
910}
911
912void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
913 assert(MAI->hasDotTypeDotSizeDirective())((void)0);
914 OS << "\t.size\t";
915 Symbol->print(OS, MAI);
916 OS << ", ";
917 Value->print(OS, MAI);
918 EmitEOL();
919}
920
921void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
922 unsigned ByteAlignment) {
923 OS << "\t.comm\t";
924 Symbol->print(OS, MAI);
925 OS << ',' << Size;
926
927 if (ByteAlignment != 0) {
928 if (MAI->getCOMMDirectiveAlignmentIsInBytes())
929 OS << ',' << ByteAlignment;
930 else
931 OS << ',' << Log2_32(ByteAlignment);
932 }
933 EmitEOL();
934
935 // Print symbol's rename (original name contains invalid character(s)) if
936 // there is one.
937 MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(Symbol);
938 if (XSym && XSym->hasRename())
939 emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
940
941}
942
943void MCAsmStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
944 unsigned ByteAlign) {
945 OS << "\t.lcomm\t";
946 Symbol->print(OS, MAI);
947 OS << ',' << Size;
948
949 if (ByteAlign > 1) {
950 switch (MAI->getLCOMMDirectiveAlignmentType()) {
951 case LCOMM::NoAlignment:
952 llvm_unreachable("alignment not supported on .lcomm!")__builtin_unreachable();
953 case LCOMM::ByteAlignment:
954 OS << ',' << ByteAlign;
955 break;
956 case LCOMM::Log2Alignment:
957 assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2")((void)0);
958 OS << ',' << Log2_32(ByteAlign);
959 break;
960 }
961 }
962 EmitEOL();
963}
964
965void MCAsmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
966 uint64_t Size, unsigned ByteAlignment,
967 SMLoc Loc) {
968 if (Symbol)
969 AssignFragment(Symbol, &Section->getDummyFragment());
970
971 // Note: a .zerofill directive does not switch sections.
972 OS << ".zerofill ";
973
974 assert(Section->getVariant() == MCSection::SV_MachO &&((void)0)
975 ".zerofill is a Mach-O specific directive")((void)0);
976 // This is a mach-o specific directive.
977
978 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
979 OS << MOSection->getSegmentName() << "," << MOSection->getName();
980
981 if (Symbol) {
982 OS << ',';
983 Symbol->print(OS, MAI);
984 OS << ',' << Size;
985 if (ByteAlignment != 0)
986 OS << ',' << Log2_32(ByteAlignment);
987 }
988 EmitEOL();
989}
990
991// .tbss sym, size, align
992// This depends that the symbol has already been mangled from the original,
993// e.g. _a.
994void MCAsmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
995 uint64_t Size, unsigned ByteAlignment) {
996 AssignFragment(Symbol, &Section->getDummyFragment());
997
998 assert(Symbol && "Symbol shouldn't be NULL!")((void)0);
999 // Instead of using the Section we'll just use the shortcut.
1000
1001 assert(Section->getVariant() == MCSection::SV_MachO &&((void)0)
1002 ".zerofill is a Mach-O specific directive")((void)0);
1003 // This is a mach-o specific directive and section.
1004
1005 OS << ".tbss ";
1006 Symbol->print(OS, MAI);
1007 OS << ", " << Size;
1008
1009 // Output align if we have it. We default to 1 so don't bother printing
1010 // that.
1011 if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment);
1012
1013 EmitEOL();
1014}
1015
1016static inline bool isPrintableString(StringRef Data) {
1017 const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1018 for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1019 if (!isPrint(C))
1020 return false;
1021 }
1022 return isPrint(Data.back()) || Data.back() == 0;
1023}
1024
1025static inline char toOctal(int X) { return (X&7)+'0'; }
1026
1027static void PrintByteList(StringRef Data, raw_ostream &OS,
1028 MCAsmInfo::AsmCharLiteralSyntax ACLS) {
1029 assert(!Data.empty() && "Cannot generate an empty list.")((void)0);
1030 const auto printCharacterInOctal = [&OS](unsigned char C) {
1031 OS << '0';
1032 OS << toOctal(C >> 6);
1033 OS << toOctal(C >> 3);
1034 OS << toOctal(C >> 0);
1035 };
1036 const auto printOneCharacterFor = [printCharacterInOctal](
1037 auto printOnePrintingCharacter) {
1038 return [printCharacterInOctal, printOnePrintingCharacter](unsigned char C) {
1039 if (isPrint(C)) {
1040 printOnePrintingCharacter(static_cast<char>(C));
1041 return;
1042 }
1043 printCharacterInOctal(C);
1044 };
1045 };
1046 const auto printCharacterList = [Data, &OS](const auto &printOneCharacter) {
1047 const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1048 for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1049 printOneCharacter(C);
1050 OS << ',';
1051 }
1052 printOneCharacter(*(EndPtr - 1));
1053 };
1054 switch (ACLS) {
1055 case MCAsmInfo::ACLS_Unknown:
1056 printCharacterList(printCharacterInOctal);
1057 return;
1058 case MCAsmInfo::ACLS_SingleQuotePrefix:
1059 printCharacterList(printOneCharacterFor([&OS](char C) {
1060 const char AsmCharLitBuf[2] = {'\'', C};
1061 OS << StringRef(AsmCharLitBuf, sizeof(AsmCharLitBuf));
1062 }));
1063 return;
1064 }
1065 llvm_unreachable("Invalid AsmCharLiteralSyntax value!")__builtin_unreachable();
1066}
1067
1068void MCAsmStreamer::PrintQuotedString(StringRef Data, raw_ostream &OS) const {
1069 OS << '"';
1070
1071 if (MAI->hasPairedDoubleQuoteStringConstants()) {
1072 for (unsigned i = 0, e = Data.size(); i != e; ++i) {
1073 unsigned char C = Data[i];
1074 if (C == '"')
1075 OS << "\"\"";
1076 else
1077 OS << (char)C;
1078 }
1079 } else {
1080 for (unsigned i = 0, e = Data.size(); i != e; ++i) {
1081 unsigned char C = Data[i];
1082 if (C == '"' || C == '\\') {
1083 OS << '\\' << (char)C;
1084 continue;
1085 }
1086
1087 if (isPrint((unsigned char)C)) {
1088 OS << (char)C;
1089 continue;
1090 }
1091
1092 switch (C) {
1093 case '\b':
1094 OS << "\\b";
1095 break;
1096 case '\f':
1097 OS << "\\f";
1098 break;
1099 case '\n':
1100 OS << "\\n";
1101 break;
1102 case '\r':
1103 OS << "\\r";
1104 break;
1105 case '\t':
1106 OS << "\\t";
1107 break;
1108 default:
1109 OS << '\\';
1110 OS << toOctal(C >> 6);
1111 OS << toOctal(C >> 3);
1112 OS << toOctal(C >> 0);
1113 break;
1114 }
1115 }
1116 }
1117
1118 OS << '"';
1119}
1120
1121void MCAsmStreamer::emitBytes(StringRef Data) {
1122 assert(getCurrentSectionOnly() &&((void)0)
1123 "Cannot emit contents before setting section!")((void)0);
1124 if (Data.empty()) return;
1125
1126 const auto emitAsString = [this](StringRef Data) {
1127 // If the data ends with 0 and the target supports .asciz, use it, otherwise
1128 // use .ascii or a byte-list directive
1129 if (MAI->getAscizDirective() && Data.back() == 0) {
1130 OS << MAI->getAscizDirective();
1131 Data = Data.substr(0, Data.size() - 1);
1132 } else if (LLVM_LIKELY(MAI->getAsciiDirective())__builtin_expect((bool)(MAI->getAsciiDirective()), true)) {
1133 OS << MAI->getAsciiDirective();
1134 } else if (MAI->hasPairedDoubleQuoteStringConstants() &&
1135 isPrintableString(Data)) {
1136 // For target with DoubleQuoteString constants, .string and .byte are used
1137 // as replacement of .asciz and .ascii.
1138 assert(MAI->getPlainStringDirective() &&((void)0)
1139 "hasPairedDoubleQuoteStringConstants target must support "((void)0)
1140 "PlainString Directive")((void)0);
1141 assert(MAI->getByteListDirective() &&((void)0)
1142 "hasPairedDoubleQuoteStringConstants target must support ByteList "((void)0)
1143 "Directive")((void)0);
1144 if (Data.back() == 0) {
1145 OS << MAI->getPlainStringDirective();
1146 Data = Data.substr(0, Data.size() - 1);
1147 } else {
1148 OS << MAI->getByteListDirective();
1149 }
1150 } else if (MAI->getByteListDirective()) {
1151 OS << MAI->getByteListDirective();
1152 PrintByteList(Data, OS, MAI->characterLiteralSyntax());
1153 EmitEOL();
1154 return true;
1155 } else {
1156 return false;
1157 }
1158
1159 PrintQuotedString(Data, OS);
1160 EmitEOL();
1161 return true;
1162 };
1163
1164 if (Data.size() != 1 && emitAsString(Data))
1165 return;
1166
1167 // Only single byte is provided or no ascii, asciz, or byte-list directives
1168 // are applicable. Emit as vector of individual 8bits data elements.
1169 if (MCTargetStreamer *TS = getTargetStreamer()) {
1170 TS->emitRawBytes(Data);
1171 return;
1172 }
1173 const char *Directive = MAI->getData8bitsDirective();
1174 for (const unsigned char C : Data.bytes()) {
1175 OS << Directive << (unsigned)C;
1176 EmitEOL();
1177 }
1178}
1179
1180void MCAsmStreamer::emitBinaryData(StringRef Data) {
1181 // This is binary data. Print it in a grid of hex bytes for readability.
1182 const size_t Cols = 4;
1183 for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
1184 size_t J = I, EJ = std::min(I + Cols, Data.size());
1185 assert(EJ > 0)((void)0);
1186 OS << MAI->getData8bitsDirective();
1187 for (; J < EJ - 1; ++J)
1188 OS << format("0x%02x", uint8_t(Data[J])) << ", ";
1189 OS << format("0x%02x", uint8_t(Data[J]));
1190 EmitEOL();
1191 }
1192}
1193
1194void MCAsmStreamer::emitIntValue(uint64_t Value, unsigned Size) {
1195 emitValue(MCConstantExpr::create(Value, getContext()), Size);
1196}
1197
1198void MCAsmStreamer::emitIntValueInHex(uint64_t Value, unsigned Size) {
1199 emitValue(MCConstantExpr::create(Value, getContext(), true), Size);
1200}
1201
1202void MCAsmStreamer::emitIntValueInHexWithPadding(uint64_t Value,
1203 unsigned Size) {
1204 emitValue(MCConstantExpr::create(Value, getContext(), true, Size), Size);
1205}
1206
1207void MCAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
1208 SMLoc Loc) {
1209 assert(Size <= 8 && "Invalid size")((void)0);
1210 assert(getCurrentSectionOnly() &&((void)0)
1211 "Cannot emit contents before setting section!")((void)0);
1212 const char *Directive = nullptr;
1213 switch (Size) {
1
Control jumps to 'case 1:' at line 1215
1214 default: break;
1215 case 1: Directive = MAI->getData8bitsDirective(); break;
2
Execution continues on line 1221
1216 case 2: Directive = MAI->getData16bitsDirective(); break;
1217 case 4: Directive = MAI->getData32bitsDirective(); break;
1218 case 8: Directive = MAI->getData64bitsDirective(); break;
1219 }
1220
1221 if (!Directive) {
3
Assuming 'Directive' is null
4
Taking true branch
1222 int64_t IntValue;
1223 if (!Value->evaluateAsAbsolute(IntValue))
5
Assuming the condition is false
6
Taking false branch
1224 report_fatal_error("Don't know how to emit this value.");
1225
1226 // We couldn't handle the requested integer size so we fallback by breaking
1227 // the request down into several, smaller, integers.
1228 // Since sizes greater or equal to "Size" are invalid, we use the greatest
1229 // power of 2 that is less than "Size" as our largest piece of granularity.
1230 bool IsLittleEndian = MAI->isLittleEndian();
1231 for (unsigned Emitted = 0; Emitted != Size;) {
7
Loop condition is true. Entering loop body
1232 unsigned Remaining = Size - Emitted;
1233 // The size of our partial emission must be a power of two less than
1234 // Size.
1235 unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1));
1236 // Calculate the byte offset of our partial emission taking into account
1237 // the endianness of the target.
1238 unsigned ByteOffset =
1239 IsLittleEndian ? Emitted : (Remaining - EmissionSize);
8
Assuming 'IsLittleEndian' is true
9
'?' condition is true
1240 uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
1241 // We truncate our partial emission to fit within the bounds of the
1242 // emission domain. This produces nicer output and silences potential
1243 // truncation warnings when round tripping through another assembler.
1244 uint64_t Shift = 64 - EmissionSize * 8;
10
'Shift' initialized to 64
1245 assert(Shift < static_cast<uint64_t>(((void)0)
1246 std::numeric_limits<unsigned long long>::digits) &&((void)0)
1247 "undefined behavior")((void)0);
1248 ValueToEmit &= ~0ULL >> Shift;
11
The result of the right shift is undefined due to shifting by '64', which is greater or equal to the width of type 'unsigned long long'
1249 emitIntValue(ValueToEmit, EmissionSize);
1250 Emitted += EmissionSize;
1251 }
1252 return;
1253 }
1254
1255 assert(Directive && "Invalid size for machine code value!")((void)0);
1256 OS << Directive;
1257 if (MCTargetStreamer *TS = getTargetStreamer()) {
1258 TS->emitValue(Value);
1259 } else {
1260 Value->print(OS, MAI);
1261 EmitEOL();
1262 }
1263}
1264
1265void MCAsmStreamer::emitULEB128Value(const MCExpr *Value) {
1266 int64_t IntValue;
1267 if (Value->evaluateAsAbsolute(IntValue)) {
1268 emitULEB128IntValue(IntValue);
1269 return;
1270 }
1271 OS << "\t.uleb128 ";
1272 Value->print(OS, MAI);
1273 EmitEOL();
1274}
1275
1276void MCAsmStreamer::emitSLEB128Value(const MCExpr *Value) {
1277 int64_t IntValue;
1278 if (Value->evaluateAsAbsolute(IntValue)) {
1279 emitSLEB128IntValue(IntValue);
1280 return;
1281 }
1282 OS << "\t.sleb128 ";
1283 Value->print(OS, MAI);
1284 EmitEOL();
1285}
1286
1287void MCAsmStreamer::emitDTPRel64Value(const MCExpr *Value) {
1288 assert(MAI->getDTPRel64Directive() != nullptr)((void)0);
1289 OS << MAI->getDTPRel64Directive();
1290 Value->print(OS, MAI);
1291 EmitEOL();
1292}
1293
1294void MCAsmStreamer::emitDTPRel32Value(const MCExpr *Value) {
1295 assert(MAI->getDTPRel32Directive() != nullptr)((void)0);
1296 OS << MAI->getDTPRel32Directive();
1297 Value->print(OS, MAI);
1298 EmitEOL();
1299}
1300
1301void MCAsmStreamer::emitTPRel64Value(const MCExpr *Value) {
1302 assert(MAI->getTPRel64Directive() != nullptr)((void)0);
1303 OS << MAI->getTPRel64Directive();
1304 Value->print(OS, MAI);
1305 EmitEOL();
1306}
1307
1308void MCAsmStreamer::emitTPRel32Value(const MCExpr *Value) {
1309 assert(MAI->getTPRel32Directive() != nullptr)((void)0);
1310 OS << MAI->getTPRel32Directive();
1311 Value->print(OS, MAI);
1312 EmitEOL();
1313}
1314
1315void MCAsmStreamer::emitGPRel64Value(const MCExpr *Value) {
1316 assert(MAI->getGPRel64Directive() != nullptr)((void)0);
1317 OS << MAI->getGPRel64Directive();
1318 Value->print(OS, MAI);
1319 EmitEOL();
1320}
1321
1322void MCAsmStreamer::emitGPRel32Value(const MCExpr *Value) {
1323 assert(MAI->getGPRel32Directive() != nullptr)((void)0);
1324 OS << MAI->getGPRel32Directive();
1325 Value->print(OS, MAI);
1326 EmitEOL();
1327}
1328
1329void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
1330 SMLoc Loc) {
1331 int64_t IntNumBytes;
1332 const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes);
1333 if (IsAbsolute && IntNumBytes == 0)
1334 return;
1335
1336 if (const char *ZeroDirective = MAI->getZeroDirective()) {
1337 if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) {
1338 // FIXME: Emit location directives
1339 OS << ZeroDirective;
1340 NumBytes.print(OS, MAI);
1341 if (FillValue != 0)
1342 OS << ',' << (int)FillValue;
1343 EmitEOL();
1344 } else {
1345 if (!IsAbsolute)
1346 report_fatal_error(
1347 "Cannot emit non-absolute expression lengths of fill.");
1348 for (int i = 0; i < IntNumBytes; ++i) {
1349 OS << MAI->getData8bitsDirective() << (int)FillValue;
1350 EmitEOL();
1351 }
1352 }
1353 return;
1354 }
1355
1356 MCStreamer::emitFill(NumBytes, FillValue);
1357}
1358
1359void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
1360 int64_t Expr, SMLoc Loc) {
1361 // FIXME: Emit location directives
1362 OS << "\t.fill\t";
1363 NumValues.print(OS, MAI);
1364 OS << ", " << Size << ", 0x";
1365 OS.write_hex(truncateToSize(Expr, 4));
1366 EmitEOL();
1367}
1368
1369void MCAsmStreamer::emitValueToAlignment(unsigned ByteAlignment, int64_t Value,
1370 unsigned ValueSize,
1371 unsigned MaxBytesToEmit) {
1372 if (MAI->useDotAlignForAlignment()) {
1373 if (!isPowerOf2_32(ByteAlignment))
1374 report_fatal_error("Only power-of-two alignments are supported "
1375 "with .align.");
1376 OS << "\t.align\t";
1377 OS << Log2_32(ByteAlignment);
1378 EmitEOL();
1379 return;
1380 }
1381
1382 // Some assemblers don't support non-power of two alignments, so we always
1383 // emit alignments as a power of two if possible.
1384 if (isPowerOf2_32(ByteAlignment)) {
1385 switch (ValueSize) {
1386 default:
1387 llvm_unreachable("Invalid size for machine code value!")__builtin_unreachable();
1388 case 1:
1389 OS << "\t.p2align\t";
1390 break;
1391 case 2:
1392 OS << ".p2alignw ";
1393 break;
1394 case 4:
1395 OS << ".p2alignl ";
1396 break;
1397 case 8:
1398 llvm_unreachable("Unsupported alignment size!")__builtin_unreachable();
1399 }
1400
1401 OS << Log2_32(ByteAlignment);
1402
1403 if (Value || MaxBytesToEmit) {
1404 OS << ", 0x";
1405 OS.write_hex(truncateToSize(Value, ValueSize));
1406
1407 if (MaxBytesToEmit)
1408 OS << ", " << MaxBytesToEmit;
1409 }
1410 EmitEOL();
1411 return;
1412 }
1413
1414 // Non-power of two alignment. This is not widely supported by assemblers.
1415 // FIXME: Parameterize this based on MAI.
1416 switch (ValueSize) {
1417 default: llvm_unreachable("Invalid size for machine code value!")__builtin_unreachable();
1418 case 1: OS << ".balign"; break;
1419 case 2: OS << ".balignw"; break;
1420 case 4: OS << ".balignl"; break;
1421 case 8: llvm_unreachable("Unsupported alignment size!")__builtin_unreachable();
1422 }
1423
1424 OS << ' ' << ByteAlignment;
1425 OS << ", " << truncateToSize(Value, ValueSize);
1426 if (MaxBytesToEmit)
1427 OS << ", " << MaxBytesToEmit;
1428 EmitEOL();
1429}
1430
1431void MCAsmStreamer::emitCodeAlignment(unsigned ByteAlignment,
1432 unsigned MaxBytesToEmit) {
1433 // Emit with a text fill value.
1434 emitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
1435 1, MaxBytesToEmit);
1436}
1437
1438void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
1439 unsigned char Value,
1440 SMLoc Loc) {
1441 // FIXME: Verify that Offset is associated with the current section.
1442 OS << ".org ";
1443 Offset->print(OS, MAI);
1444 OS << ", " << (unsigned)Value;
1445 EmitEOL();
1446}
1447
1448void MCAsmStreamer::emitFileDirective(StringRef Filename) {
1449 assert(MAI->hasSingleParameterDotFile())((void)0);
1450 OS << "\t.file\t";
1451 PrintQuotedString(Filename, OS);
1452 EmitEOL();
1453}
1454
1455void MCAsmStreamer::emitFileDirective(StringRef Filename,
1456 StringRef CompilerVerion,
1457 StringRef TimeStamp,
1458 StringRef Description) {
1459 assert(MAI->hasFourStringsDotFile())((void)0);
1460 OS << "\t.file\t";
1461 PrintQuotedString(Filename, OS);
1462 OS << ",";
1463 if (!CompilerVerion.empty()) {
1464 PrintQuotedString(CompilerVerion, OS);
1465 }
1466 if (!TimeStamp.empty()) {
1467 OS << ",";
1468 PrintQuotedString(TimeStamp, OS);
1469 }
1470 if (!Description.empty()) {
1471 OS << ",";
1472 PrintQuotedString(Description, OS);
1473 }
1474 EmitEOL();
1475}
1476
1477void MCAsmStreamer::printDwarfFileDirective(
1478 unsigned FileNo, StringRef Directory, StringRef Filename,
1479 Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source,
1480 bool UseDwarfDirectory, raw_svector_ostream &OS) const {
1481 SmallString<128> FullPathName;
1482
1483 if (!UseDwarfDirectory && !Directory.empty()) {
1484 if (sys::path::is_absolute(Filename))
1485 Directory = "";
1486 else {
1487 FullPathName = Directory;
1488 sys::path::append(FullPathName, Filename);
1489 Directory = "";
1490 Filename = FullPathName;
1491 }
1492 }
1493
1494 OS << "\t.file\t" << FileNo << ' ';
1495 if (!Directory.empty()) {
1496 PrintQuotedString(Directory, OS);
1497 OS << ' ';
1498 }
1499 PrintQuotedString(Filename, OS);
1500 if (Checksum)
1501 OS << " md5 0x" << Checksum->digest();
1502 if (Source) {
1503 OS << " source ";
1504 PrintQuotedString(*Source, OS);
1505 }
1506}
1507
1508Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
1509 unsigned FileNo, StringRef Directory, StringRef Filename,
1510 Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, unsigned CUID) {
1511 assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer")((void)0);
1512
1513 MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
1514 unsigned NumFiles = Table.getMCDwarfFiles().size();
1515 Expected<unsigned> FileNoOrErr =
1516 Table.tryGetFile(Directory, Filename, Checksum, Source,
1517 getContext().getDwarfVersion(), FileNo);
1518 if (!FileNoOrErr)
1519 return FileNoOrErr.takeError();
1520 FileNo = FileNoOrErr.get();
1521
1522 // Return early if this file is already emitted before or if target doesn't
1523 // support .file directive.
1524 if (NumFiles == Table.getMCDwarfFiles().size() ||
1525 !MAI->usesDwarfFileAndLocDirectives())
1526 return FileNo;
1527
1528 SmallString<128> Str;
1529 raw_svector_ostream OS1(Str);
1530 printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
1531 UseDwarfDirectory, OS1);
1532
1533 if (MCTargetStreamer *TS = getTargetStreamer())
1534 TS->emitDwarfFileDirective(OS1.str());
1535 else
1536 emitRawText(OS1.str());
1537
1538 return FileNo;
1539}
1540
1541void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory,
1542 StringRef Filename,
1543 Optional<MD5::MD5Result> Checksum,
1544 Optional<StringRef> Source,
1545 unsigned CUID) {
1546 assert(CUID == 0)((void)0);
1547 // .file 0 is new for DWARF v5.
1548 if (getContext().getDwarfVersion() < 5)
1549 return;
1550 // Inform MCDwarf about the root file.
1551 getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
1552 Source);
1553
1554 // Target doesn't support .loc/.file directives, return early.
1555 if (!MAI->usesDwarfFileAndLocDirectives())
1556 return;
1557
1558 SmallString<128> Str;
1559 raw_svector_ostream OS1(Str);
1560 printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
1561 UseDwarfDirectory, OS1);
1562
1563 if (MCTargetStreamer *TS = getTargetStreamer())
1564 TS->emitDwarfFileDirective(OS1.str());
1565 else
1566 emitRawText(OS1.str());
1567}
1568
1569void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
1570 unsigned Column, unsigned Flags,
1571 unsigned Isa, unsigned Discriminator,
1572 StringRef FileName) {
1573 // If target doesn't support .loc/.file directive, we need to record the lines
1574 // same way like we do in object mode.
1575 if (!MAI->usesDwarfFileAndLocDirectives()) {
1576 // In case we see two .loc directives in a row, make sure the
1577 // first one gets a line entry.
1578 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
1579 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1580 Discriminator, FileName);
1581 return;
1582 }
1583
1584 OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
1585 if (MAI->supportsExtendedDwarfLocDirective()) {
1586 if (Flags & DWARF2_FLAG_BASIC_BLOCK(1 << 1))
1587 OS << " basic_block";
1588 if (Flags & DWARF2_FLAG_PROLOGUE_END(1 << 2))
1589 OS << " prologue_end";
1590 if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN(1 << 3))
1591 OS << " epilogue_begin";
1592
1593 unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
1594 if ((Flags & DWARF2_FLAG_IS_STMT(1 << 0)) != (OldFlags & DWARF2_FLAG_IS_STMT(1 << 0))) {
1595 OS << " is_stmt ";
1596
1597 if (Flags & DWARF2_FLAG_IS_STMT(1 << 0))
1598 OS << "1";
1599 else
1600 OS << "0";
1601 }
1602
1603 if (Isa)
1604 OS << " isa " << Isa;
1605 if (Discriminator)
1606 OS << " discriminator " << Discriminator;
1607 }
1608
1609 if (IsVerboseAsm) {
1610 OS.PadToColumn(MAI->getCommentColumn());
1611 OS << MAI->getCommentString() << ' ' << FileName << ':'
1612 << Line << ':' << Column;
1613 }
1614 EmitEOL();
1615 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1616 Discriminator, FileName);
1617}
1618
1619MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
1620 // Always use the zeroth line table, since asm syntax only supports one line
1621 // table for now.
1622 return MCStreamer::getDwarfLineTableSymbol(0);
1623}
1624
1625bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
1626 ArrayRef<uint8_t> Checksum,
1627 unsigned ChecksumKind) {
1628 if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
1629 ChecksumKind))
1630 return false;
1631
1632 OS << "\t.cv_file\t" << FileNo << ' ';
1633 PrintQuotedString(Filename, OS);
1634
1635 if (!ChecksumKind) {
1636 EmitEOL();
1637 return true;
1638 }
1639
1640 OS << ' ';
1641 PrintQuotedString(toHex(Checksum), OS);
1642 OS << ' ' << ChecksumKind;
1643
1644 EmitEOL();
1645 return true;
1646}
1647
1648bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) {
1649 OS << "\t.cv_func_id " << FuncId << '\n';
1650 return MCStreamer::EmitCVFuncIdDirective(FuncId);
1651}
1652
1653bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
1654 unsigned IAFunc,
1655 unsigned IAFile,
1656 unsigned IALine, unsigned IACol,
1657 SMLoc Loc) {
1658 OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
1659 << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
1660 return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
1661 IALine, IACol, Loc);
1662}
1663
1664void MCAsmStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
1665 unsigned Line, unsigned Column,
1666 bool PrologueEnd, bool IsStmt,
1667 StringRef FileName, SMLoc Loc) {
1668 // Validate the directive.
1669 if (!checkCVLocSection(FunctionId, FileNo, Loc))
1670 return;
1671
1672 OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
1673 << Column;
1674 if (PrologueEnd)
1675 OS << " prologue_end";
1676
1677 if (IsStmt)
1678 OS << " is_stmt 1";
1679
1680 if (IsVerboseAsm) {
1681 OS.PadToColumn(MAI->getCommentColumn());
1682 OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
1683 << Column;
1684 }
1685 EmitEOL();
1686}
1687
1688void MCAsmStreamer::emitCVLinetableDirective(unsigned FunctionId,
1689 const MCSymbol *FnStart,
1690 const MCSymbol *FnEnd) {
1691 OS << "\t.cv_linetable\t" << FunctionId << ", ";
1692 FnStart->print(OS, MAI);
1693 OS << ", ";
1694 FnEnd->print(OS, MAI);
1695 EmitEOL();
1696 this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart, FnEnd);
1697}
1698
1699void MCAsmStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
1700 unsigned SourceFileId,
1701 unsigned SourceLineNum,
1702 const MCSymbol *FnStartSym,
1703 const MCSymbol *FnEndSym) {
1704 OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
1705 << ' ' << SourceLineNum << ' ';
1706 FnStartSym->print(OS, MAI);
1707 OS << ' ';
1708 FnEndSym->print(OS, MAI);
1709 EmitEOL();
1710 this->MCStreamer::emitCVInlineLinetableDirective(
1711 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
1712}
1713
1714void MCAsmStreamer::PrintCVDefRangePrefix(
1715 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) {
1716 OS << "\t.cv_def_range\t";
1717 for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
1718 OS << ' ';
1719 Range.first->print(OS, MAI);
1720 OS << ' ';
1721 Range.second->print(OS, MAI);
1722 }
1723}
1724
1725void MCAsmStreamer::emitCVDefRangeDirective(
1726 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1727 codeview::DefRangeRegisterRelHeader DRHdr) {
1728 PrintCVDefRangePrefix(Ranges);
1729 OS << ", reg_rel, ";
1730 OS << DRHdr.Register << ", " << DRHdr.Flags << ", "
1731 << DRHdr.BasePointerOffset;
1732 EmitEOL();
1733}
1734
1735void MCAsmStreamer::emitCVDefRangeDirective(
1736 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1737 codeview::DefRangeSubfieldRegisterHeader DRHdr) {
1738 PrintCVDefRangePrefix(Ranges);
1739 OS << ", subfield_reg, ";
1740 OS << DRHdr.Register << ", " << DRHdr.OffsetInParent;
1741 EmitEOL();
1742}
1743
1744void MCAsmStreamer::emitCVDefRangeDirective(
1745 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1746 codeview::DefRangeRegisterHeader DRHdr) {
1747 PrintCVDefRangePrefix(Ranges);
1748 OS << ", reg, ";
1749 OS << DRHdr.Register;
1750 EmitEOL();
1751}
1752
1753void MCAsmStreamer::emitCVDefRangeDirective(
1754 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1755 codeview::DefRangeFramePointerRelHeader DRHdr) {
1756 PrintCVDefRangePrefix(Ranges);
1757 OS << ", frame_ptr_rel, ";
1758 OS << DRHdr.Offset;
1759 EmitEOL();
1760}
1761
1762void MCAsmStreamer::emitCVStringTableDirective() {
1763 OS << "\t.cv_stringtable";
1764 EmitEOL();
1765}
1766
1767void MCAsmStreamer::emitCVFileChecksumsDirective() {
1768 OS << "\t.cv_filechecksums";
1769 EmitEOL();
1770}
1771
1772void MCAsmStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
1773 OS << "\t.cv_filechecksumoffset\t" << FileNo;
1774 EmitEOL();
1775}
1776
1777void MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
1778 OS << "\t.cv_fpo_data\t";
1779 ProcSym->print(OS, MAI);
1780 EmitEOL();
1781}
1782
1783void MCAsmStreamer::emitIdent(StringRef IdentString) {
1784 assert(MAI->hasIdentDirective() && ".ident directive not supported")((void)0);
1785 OS << "\t.ident\t";
1786 PrintQuotedString(IdentString, OS);
1787 EmitEOL();
1788}
1789
1790void MCAsmStreamer::emitCFISections(bool EH, bool Debug) {
1791 MCStreamer::emitCFISections(EH, Debug);
1792 OS << "\t.cfi_sections ";
1793 if (EH) {
1794 OS << ".eh_frame";
1795 if (Debug)
1796 OS << ", .debug_frame";
1797 } else if (Debug) {
1798 OS << ".debug_frame";
1799 }
1800
1801 EmitEOL();
1802}
1803
1804void MCAsmStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
1805 OS << "\t.cfi_startproc";
1806 if (Frame.IsSimple)
1807 OS << " simple";
1808 EmitEOL();
1809}
1810
1811void MCAsmStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
1812 MCStreamer::emitCFIEndProcImpl(Frame);
1813 OS << "\t.cfi_endproc";
1814 EmitEOL();
1815}
1816
1817void MCAsmStreamer::EmitRegisterName(int64_t Register) {
1818 if (!MAI->useDwarfRegNumForCFI()) {
1819 // User .cfi_* directives can use arbitrary DWARF register numbers, not
1820 // just ones that map to LLVM register numbers and have known names.
1821 // Fall back to using the original number directly if no name is known.
1822 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
1823 if (Optional<unsigned> LLVMRegister = MRI->getLLVMRegNum(Register, true)) {
1824 InstPrinter->printRegName(OS, *LLVMRegister);
1825 return;
1826 }
1827 }
1828 OS << Register;
1829}
1830
1831void MCAsmStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset) {
1832 MCStreamer::emitCFIDefCfa(Register, Offset);
1833 OS << "\t.cfi_def_cfa ";
1834 EmitRegisterName(Register);
1835 OS << ", " << Offset;
1836 EmitEOL();
1837}
1838
1839void MCAsmStreamer::emitCFIDefCfaOffset(int64_t Offset) {
1840 MCStreamer::emitCFIDefCfaOffset(Offset);
1841 OS << "\t.cfi_def_cfa_offset " << Offset;
1842 EmitEOL();
1843}
1844
1845void MCAsmStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,
1846 int64_t AddressSpace) {
1847 MCStreamer::emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace);
1848 OS << "\t.cfi_llvm_def_aspace_cfa ";
1849 EmitRegisterName(Register);
1850 OS << ", " << Offset;
1851 OS << ", " << AddressSpace;
1852 EmitEOL();
1853}
1854
1855static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
1856 OS << "\t.cfi_escape ";
1857 if (!Values.empty()) {
1858 size_t e = Values.size() - 1;
1859 for (size_t i = 0; i < e; ++i)
1860 OS << format("0x%02x", uint8_t(Values[i])) << ", ";
1861 OS << format("0x%02x", uint8_t(Values[e]));
1862 }
1863}
1864
1865void MCAsmStreamer::emitCFIEscape(StringRef Values) {
1866 MCStreamer::emitCFIEscape(Values);
1867 PrintCFIEscape(OS, Values);
1868 EmitEOL();
1869}
1870
1871void MCAsmStreamer::emitCFIGnuArgsSize(int64_t Size) {
1872 MCStreamer::emitCFIGnuArgsSize(Size);
1873
1874 uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
1875 unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
1876
1877 PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
1878 EmitEOL();
1879}
1880
1881void MCAsmStreamer::emitCFIDefCfaRegister(int64_t Register) {
1882 MCStreamer::emitCFIDefCfaRegister(Register);
1883 OS << "\t.cfi_def_cfa_register ";
1884 EmitRegisterName(Register);
1885 EmitEOL();
1886}
1887
1888void MCAsmStreamer::emitCFIOffset(int64_t Register, int64_t Offset) {
1889 this->MCStreamer::emitCFIOffset(Register, Offset);
1890 OS << "\t.cfi_offset ";
1891 EmitRegisterName(Register);
1892 OS << ", " << Offset;
1893 EmitEOL();
1894}
1895
1896void MCAsmStreamer::emitCFIPersonality(const MCSymbol *Sym,
1897 unsigned Encoding) {
1898 MCStreamer::emitCFIPersonality(Sym, Encoding);
1899 OS << "\t.cfi_personality " << Encoding << ", ";
1900 Sym->print(OS, MAI);
1901 EmitEOL();
1902}
1903
1904void MCAsmStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
1905 MCStreamer::emitCFILsda(Sym, Encoding);
1906 OS << "\t.cfi_lsda " << Encoding << ", ";
1907 Sym->print(OS, MAI);
1908 EmitEOL();
1909}
1910
1911void MCAsmStreamer::emitCFIRememberState() {
1912 MCStreamer::emitCFIRememberState();
1913 OS << "\t.cfi_remember_state";
1914 EmitEOL();
1915}
1916
1917void MCAsmStreamer::emitCFIRestoreState() {
1918 MCStreamer::emitCFIRestoreState();
1919 OS << "\t.cfi_restore_state";
1920 EmitEOL();
1921}
1922
1923void MCAsmStreamer::emitCFIRestore(int64_t Register) {
1924 MCStreamer::emitCFIRestore(Register);
1925 OS << "\t.cfi_restore ";
1926 EmitRegisterName(Register);
1927 EmitEOL();
1928}
1929
1930void MCAsmStreamer::emitCFISameValue(int64_t Register) {
1931 MCStreamer::emitCFISameValue(Register);
1932 OS << "\t.cfi_same_value ";
1933 EmitRegisterName(Register);
1934 EmitEOL();
1935}
1936
1937void MCAsmStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset) {
1938 MCStreamer::emitCFIRelOffset(Register, Offset);
1939 OS << "\t.cfi_rel_offset ";
1940 EmitRegisterName(Register);
1941 OS << ", " << Offset;
1942 EmitEOL();
1943}
1944
1945void MCAsmStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment) {
1946 MCStreamer::emitCFIAdjustCfaOffset(Adjustment);
1947 OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
1948 EmitEOL();
1949}
1950
1951void MCAsmStreamer::emitCFISignalFrame() {
1952 MCStreamer::emitCFISignalFrame();
1953 OS << "\t.cfi_signal_frame";
1954 EmitEOL();
1955}
1956
1957void MCAsmStreamer::emitCFIUndefined(int64_t Register) {
1958 MCStreamer::emitCFIUndefined(Register);
1959 OS << "\t.cfi_undefined ";
1960 EmitRegisterName(Register);
1961 EmitEOL();
1962}
1963
1964void MCAsmStreamer::emitCFIRegister(int64_t Register1, int64_t Register2) {
1965 MCStreamer::emitCFIRegister(Register1, Register2);
1966 OS << "\t.cfi_register ";
1967 EmitRegisterName(Register1);
1968 OS << ", ";
1969 EmitRegisterName(Register2);
1970 EmitEOL();
1971}
1972
1973void MCAsmStreamer::emitCFIWindowSave() {
1974 MCStreamer::emitCFIWindowSave();
1975 OS << "\t.cfi_window_save";
1976 EmitEOL();
1977}
1978
1979void MCAsmStreamer::emitCFINegateRAState() {
1980 MCStreamer::emitCFINegateRAState();
1981 OS << "\t.cfi_negate_ra_state";
1982 EmitEOL();
1983}
1984
1985void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {
1986 MCStreamer::emitCFIReturnColumn(Register);
1987 OS << "\t.cfi_return_column ";
1988 EmitRegisterName(Register);
1989 EmitEOL();
1990}
1991
1992void MCAsmStreamer::emitCFIBKeyFrame() {
1993 MCStreamer::emitCFIBKeyFrame();
1994 OS << "\t.cfi_b_key_frame";
1995 EmitEOL();
1996}
1997
1998void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
1999 MCStreamer::EmitWinCFIStartProc(Symbol, Loc);
2000
2001 OS << ".seh_proc ";
2002 Symbol->print(OS, MAI);
2003 EmitEOL();
2004}
2005
2006void MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) {
2007 MCStreamer::EmitWinCFIEndProc(Loc);
2008
2009 OS << "\t.seh_endproc";
2010 EmitEOL();
2011}
2012
2013void MCAsmStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
2014 MCStreamer::EmitWinCFIFuncletOrFuncEnd(Loc);
2015
2016 OS << "\t.seh_endfunclet";
2017 EmitEOL();
2018}
2019
2020void MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) {
2021 MCStreamer::EmitWinCFIStartChained(Loc);
2022
2023 OS << "\t.seh_startchained";
2024 EmitEOL();
2025}
2026
2027void MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) {
2028 MCStreamer::EmitWinCFIEndChained(Loc);
2029
2030 OS << "\t.seh_endchained";
2031 EmitEOL();
2032}
2033
2034void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
2035 bool Except, SMLoc Loc) {
2036 MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc);
2037
2038 OS << "\t.seh_handler ";
2039 Sym->print(OS, MAI);
2040 if (Unwind)
2041 OS << ", @unwind";
2042 if (Except)
2043 OS << ", @except";
2044 EmitEOL();
2045}
2046
2047void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) {
2048 MCStreamer::EmitWinEHHandlerData(Loc);
2049
2050 // Switch sections. Don't call SwitchSection directly, because that will
2051 // cause the section switch to be visible in the emitted assembly.
2052 // We only do this so the section switch that terminates the handler
2053 // data block is visible.
2054 WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
2055
2056 // Do nothing if no frame is open. MCStreamer should've already reported an
2057 // error.
2058 if (!CurFrame)
2059 return;
2060
2061 MCSection *TextSec = &CurFrame->Function->getSection();
2062 MCSection *XData = getAssociatedXDataSection(TextSec);
2063 SwitchSectionNoChange(XData);
2064
2065 OS << "\t.seh_handlerdata";
2066 EmitEOL();
2067}
2068
2069void MCAsmStreamer::EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
2070 MCStreamer::EmitWinCFIPushReg(Register, Loc);
2071
2072 OS << "\t.seh_pushreg ";
2073 InstPrinter->printRegName(OS, Register);
2074 EmitEOL();
2075}
2076
2077void MCAsmStreamer::EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
2078 SMLoc Loc) {
2079 MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc);
2080
2081 OS << "\t.seh_setframe ";
2082 InstPrinter->printRegName(OS, Register);
2083 OS << ", " << Offset;
2084 EmitEOL();
2085}
2086
2087void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
2088 MCStreamer::EmitWinCFIAllocStack(Size, Loc);
2089
2090 OS << "\t.seh_stackalloc " << Size;
2091 EmitEOL();
2092}
2093
2094void MCAsmStreamer::EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
2095 SMLoc Loc) {
2096 MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc);
2097
2098 OS << "\t.seh_savereg ";
2099 InstPrinter->printRegName(OS, Register);
2100 OS << ", " << Offset;
2101 EmitEOL();
2102}
2103
2104void MCAsmStreamer::EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
2105 SMLoc Loc) {
2106 MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc);
2107
2108 OS << "\t.seh_savexmm ";
2109 InstPrinter->printRegName(OS, Register);
2110 OS << ", " << Offset;
2111 EmitEOL();
2112}
2113
2114void MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
2115 MCStreamer::EmitWinCFIPushFrame(Code, Loc);
2116
2117 OS << "\t.seh_pushframe";
2118 if (Code)
2119 OS << " @code";
2120 EmitEOL();
2121}
2122
2123void MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
2124 MCStreamer::EmitWinCFIEndProlog(Loc);
2125
2126 OS << "\t.seh_endprologue";
2127 EmitEOL();
2128}
2129
2130void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
2131 const MCSymbolRefExpr *To,
2132 uint64_t Count) {
2133 OS << "\t.cg_profile ";
2134 From->getSymbol().print(OS, MAI);
2135 OS << ", ";
2136 To->getSymbol().print(OS, MAI);
2137 OS << ", " << Count;
2138 EmitEOL();
2139}
2140
2141void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
2142 const MCSubtargetInfo &STI) {
2143 raw_ostream &OS = GetCommentOS();
2144 SmallString<256> Code;
2145 SmallVector<MCFixup, 4> Fixups;
2146 raw_svector_ostream VecOS(Code);
2147
2148 // If we have no code emitter, don't emit code.
2149 if (!getAssembler().getEmitterPtr())
2150 return;
2151
2152 getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
2153
2154 // If we are showing fixups, create symbolic markers in the encoded
2155 // representation. We do this by making a per-bit map to the fixup item index,
2156 // then trying to display it as nicely as possible.
2157 SmallVector<uint8_t, 64> FixupMap;
2158 FixupMap.resize(Code.size() * 8);
2159 for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
2160 FixupMap[i] = 0;
2161
2162 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
2163 MCFixup &F = Fixups[i];
2164 const MCFixupKindInfo &Info =
2165 getAssembler().getBackend().getFixupKindInfo(F.getKind());
2166 for (unsigned j = 0; j != Info.TargetSize; ++j) {
2167 unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
2168 assert(Index < Code.size() * 8 && "Invalid offset in fixup!")((void)0);
2169 FixupMap[Index] = 1 + i;
2170 }
2171 }
2172
2173 // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
2174 // high order halfword of a 32-bit Thumb2 instruction is emitted first.
2175 OS << "encoding: [";
2176 for (unsigned i = 0, e = Code.size(); i != e; ++i) {
2177 if (i)
2178 OS << ',';
2179
2180 // See if all bits are the same map entry.
2181 uint8_t MapEntry = FixupMap[i * 8 + 0];
2182 for (unsigned j = 1; j != 8; ++j) {
2183 if (FixupMap[i * 8 + j] == MapEntry)
2184 continue;
2185
2186 MapEntry = uint8_t(~0U);
2187 break;
2188 }
2189
2190 if (MapEntry != uint8_t(~0U)) {
2191 if (MapEntry == 0) {
2192 OS << format("0x%02x", uint8_t(Code[i]));
2193 } else {
2194 if (Code[i]) {
2195 // FIXME: Some of the 8 bits require fix up.
2196 OS << format("0x%02x", uint8_t(Code[i])) << '\''
2197 << char('A' + MapEntry - 1) << '\'';
2198 } else
2199 OS << char('A' + MapEntry - 1);
2200 }
2201 } else {
2202 // Otherwise, write out in binary.
2203 OS << "0b";
2204 for (unsigned j = 8; j--;) {
2205 unsigned Bit = (Code[i] >> j) & 1;
2206
2207 unsigned FixupBit;
2208 if (MAI->isLittleEndian())
2209 FixupBit = i * 8 + j;
2210 else
2211 FixupBit = i * 8 + (7-j);
2212
2213 if (uint8_t MapEntry = FixupMap[FixupBit]) {
2214 assert(Bit == 0 && "Encoder wrote into fixed up bit!")((void)0);
2215 OS << char('A' + MapEntry - 1);
2216 } else
2217 OS << Bit;
2218 }
2219 }
2220 }
2221 OS << "]\n";
2222
2223 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
2224 MCFixup &F = Fixups[i];
2225 const MCFixupKindInfo &Info =
2226 getAssembler().getBackend().getFixupKindInfo(F.getKind());
2227 OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
2228 << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
2229 }
2230}
2231
2232void MCAsmStreamer::emitInstruction(const MCInst &Inst,
2233 const MCSubtargetInfo &STI) {
2234 assert(getCurrentSectionOnly() &&((void)0)
2235 "Cannot emit contents before setting section!")((void)0);
2236
2237 if (!MAI->usesDwarfFileAndLocDirectives())
2238 // Now that a machine instruction has been assembled into this section, make
2239 // a line entry for any .loc directive that has been seen.
2240 MCDwarfLineEntry::make(this, getCurrentSectionOnly());
2241
2242 // Show the encoding in a comment if we have a code emitter.
2243 AddEncodingComment(Inst, STI);
2244
2245 // Show the MCInst if enabled.
2246 if (ShowInst) {
2247 Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n ");
2248 GetCommentOS() << "\n";
2249 }
2250
2251 if(getTargetStreamer())
2252 getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS);
2253 else
2254 InstPrinter->printInst(&Inst, 0, "", STI, OS);
2255
2256 StringRef Comments = CommentToEmit;
2257 if (Comments.size() && Comments.back() != '\n')
2258 GetCommentOS() << "\n";
2259
2260 EmitEOL();
2261}
2262
2263void MCAsmStreamer::emitPseudoProbe(
2264 uint64_t Guid, uint64_t Index, uint64_t Type, uint64_t Attr,
2265 const MCPseudoProbeInlineStack &InlineStack) {
2266 OS << "\t.pseudoprobe\t" << Guid << " " << Index << " " << Type << " "
2267 << Attr;
2268 // Emit inline stack like
2269 // @ GUIDmain:3 @ GUIDCaller:1 @ GUIDDirectCaller:11
2270 for (const auto &Site : InlineStack)
2271 OS << " @ " << std::get<0>(Site) << ":" << std::get<1>(Site);
2272 EmitEOL();
2273}
2274
2275void MCAsmStreamer::emitBundleAlignMode(unsigned AlignPow2) {
2276 OS << "\t.bundle_align_mode " << AlignPow2;
2277 EmitEOL();
2278}
2279
2280void MCAsmStreamer::emitBundleLock(bool AlignToEnd) {
2281 OS << "\t.bundle_lock";
2282 if (AlignToEnd)
2283 OS << " align_to_end";
2284 EmitEOL();
2285}
2286
2287void MCAsmStreamer::emitBundleUnlock() {
2288 OS << "\t.bundle_unlock";
2289 EmitEOL();
2290}
2291
2292Optional<std::pair<bool, std::string>>
2293MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
2294 const MCExpr *Expr, SMLoc,
2295 const MCSubtargetInfo &STI) {
2296 OS << "\t.reloc ";
2297 Offset.print(OS, MAI);
2298 OS << ", " << Name;
2299 if (Expr) {
2300 OS << ", ";
2301 Expr->print(OS, MAI);
2302 }
2303 EmitEOL();
2304 return None;
2305}
2306
2307void MCAsmStreamer::emitAddrsig() {
2308 OS << "\t.addrsig";
2309 EmitEOL();
2310}
2311
2312void MCAsmStreamer::emitAddrsigSym(const MCSymbol *Sym) {
2313 OS << "\t.addrsig_sym ";
2314 Sym->print(OS, MAI);
2315 EmitEOL();
2316}
2317
2318/// EmitRawText - If this file is backed by an assembly streamer, this dumps
2319/// the specified string in the output .s file. This capability is
2320/// indicated by the hasRawTextSupport() predicate.
2321void MCAsmStreamer::emitRawTextImpl(StringRef String) {
2322 if (!String.empty() && String.back() == '\n')
2323 String = String.substr(0, String.size()-1);
2324 OS << String;
2325 EmitEOL();
2326}
2327
2328void MCAsmStreamer::finishImpl() {
2329 // If we are generating dwarf for assembly source files dump out the sections.
2330 if (getContext().getGenDwarfForAssembly())
2331 MCGenDwarfInfo::Emit(this);
2332
2333 // Now it is time to emit debug line sections if target doesn't support .loc
2334 // and .line directives.
2335 if (!MAI->usesDwarfFileAndLocDirectives()) {
2336 MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());
2337 return;
2338 }
2339
2340 // Emit the label for the line table, if requested - since the rest of the
2341 // line table will be defined by .loc/.file directives, and not emitted
2342 // directly, the label is the only work required here.
2343 const auto &Tables = getContext().getMCDwarfLineTables();
2344 if (!Tables.empty()) {
2345 assert(Tables.size() == 1 && "asm output only supports one line table")((void)0);
2346 if (auto *Label = Tables.begin()->second.getLabel()) {
2347 SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
2348 emitLabel(Label);
2349 }
2350 }
2351}
2352
2353void MCAsmStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) {
2354 // If the assembler on some target fills in the DWARF unit length, we
2355 // don't want to emit the length in the compiler. For example, the AIX
2356 // assembler requires the assembly file with the unit length omitted from
2357 // the debug section headers. In such cases, any label we placed occurs
2358 // after the implied length field. We need to adjust the reference here
2359 // to account for the offset introduced by the inserted length field.
2360 if (!MAI->needsDwarfSectionSizeInHeader())
2361 return;
2362 MCStreamer::emitDwarfUnitLength(Length, Comment);
2363}
2364
2365MCSymbol *MCAsmStreamer::emitDwarfUnitLength(const Twine &Prefix,
2366 const Twine &Comment) {
2367 // If the assembler on some target fills in the DWARF unit length, we
2368 // don't want to emit the length in the compiler. For example, the AIX
2369 // assembler requires the assembly file with the unit length omitted from
2370 // the debug section headers. In such cases, any label we placed occurs
2371 // after the implied length field. We need to adjust the reference here
2372 // to account for the offset introduced by the inserted length field.
2373 if (!MAI->needsDwarfSectionSizeInHeader())
2374 return getContext().createTempSymbol(Prefix + "_end");
2375 return MCStreamer::emitDwarfUnitLength(Prefix, Comment);
2376}
2377
2378void MCAsmStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) {
2379 // If the assembler on some target fills in the DWARF unit length, we
2380 // don't want to emit the length in the compiler. For example, the AIX
2381 // assembler requires the assembly file with the unit length omitted from
2382 // the debug section headers. In such cases, any label we placed occurs
2383 // after the implied length field. We need to adjust the reference here
2384 // to account for the offset introduced by the inserted length field.
2385 MCContext &Ctx = getContext();
2386 if (!MAI->needsDwarfSectionSizeInHeader()) {
2387 MCSymbol *DebugLineSymTmp = Ctx.createTempSymbol("debug_line_");
2388 // Emit the symbol which does not contain the unit length field.
2389 emitLabel(DebugLineSymTmp);
2390
2391 // Adjust the outer reference to account for the offset introduced by the
2392 // inserted length field.
2393 unsigned LengthFieldSize =
2394 dwarf::getUnitLengthFieldByteSize(Ctx.getDwarfFormat());
2395 const MCExpr *EntrySize = MCConstantExpr::create(LengthFieldSize, Ctx);
2396 const MCExpr *OuterSym = MCBinaryExpr::createSub(
2397 MCSymbolRefExpr::create(DebugLineSymTmp, Ctx), EntrySize, Ctx);
2398
2399 emitAssignment(StartSym, OuterSym);
2400 return;
2401 }
2402 MCStreamer::emitDwarfLineStartLabel(StartSym);
2403}
2404
2405void MCAsmStreamer::emitDwarfLineEndEntry(MCSection *Section,
2406 MCSymbol *LastLabel) {
2407 // If the targets write the raw debug line data for assembly output (We can
2408 // not switch to Section and add the end symbol there for assembly output)
2409 // we currently use the .text end label as any section end. This will not
2410 // impact the debugability as we will jump to the caller of the last function
2411 // in the section before we come into the .text end address.
2412 assert(!MAI->usesDwarfFileAndLocDirectives() &&((void)0)
2413 ".loc should not be generated together with raw data!")((void)0);
2414
2415 MCContext &Ctx = getContext();
2416
2417 // FIXME: use section end symbol as end of the Section. We need to consider
2418 // the explicit sections and -ffunction-sections when we try to generate or
2419 // find section end symbol for the Section.
2420 MCSection *TextSection = Ctx.getObjectFileInfo()->getTextSection();
2421 assert(TextSection->hasEnded() && ".text section is not end!")((void)0);
2422
2423 MCSymbol *SectionEnd = TextSection->getEndSymbol(Ctx);
2424 const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();
2425 emitDwarfAdvanceLineAddr(INT64_MAX0x7fffffffffffffffLL, LastLabel, SectionEnd,
2426 AsmInfo->getCodePointerSize());
2427}
2428
2429// Generate DWARF line sections for assembly mode without .loc/.file
2430void MCAsmStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
2431 const MCSymbol *LastLabel,
2432 const MCSymbol *Label,
2433 unsigned PointerSize) {
2434 assert(!MAI->usesDwarfFileAndLocDirectives() &&((void)0)
2435 ".loc/.file don't need raw data in debug line section!")((void)0);
2436
2437 // Set to new address.
2438 AddComment("Set address to " + Label->getName());
2439 emitIntValue(dwarf::DW_LNS_extended_op, 1);
2440 emitULEB128IntValue(PointerSize + 1);
2441 emitIntValue(dwarf::DW_LNE_set_address, 1);
2442 emitSymbolValue(Label, PointerSize);
2443
2444 if (!LastLabel) {
2445 // Emit the sequence for the LineDelta (from 1) and a zero address delta.
2446 AddComment("Start sequence");
2447 MCDwarfLineAddr::Emit(this, MCDwarfLineTableParams(), LineDelta, 0);
2448 return;
2449 }
2450
2451 // INT64_MAX is a signal of the end of the section. Emit DW_LNE_end_sequence
2452 // for the end of the section.
2453 if (LineDelta == INT64_MAX0x7fffffffffffffffLL) {
2454 AddComment("End sequence");
2455 emitIntValue(dwarf::DW_LNS_extended_op, 1);
2456 emitULEB128IntValue(1);
2457 emitIntValue(dwarf::DW_LNE_end_sequence, 1);
2458 return;
2459 }
2460
2461 // Advance line.
2462 AddComment("Advance line " + Twine(LineDelta));
2463 emitIntValue(dwarf::DW_LNS_advance_line, 1);
2464 emitSLEB128IntValue(LineDelta);
2465 emitIntValue(dwarf::DW_LNS_copy, 1);
2466}
2467
2468void MCAsmStreamer::doFinalizationAtSectionEnd(MCSection *Section) {
2469 // Emit section end. This is used to tell the debug line section where the end
2470 // is for a text section if we don't use .loc to represent the debug line.
2471 if (MAI->usesDwarfFileAndLocDirectives())
2472 return;
2473
2474 SwitchSectionNoChange(Section);
2475
2476 MCSymbol *Sym = getCurrentSectionOnly()->getEndSymbol(getContext());
2477
2478 if (!Sym->isInSection())
2479 emitLabel(Sym);
2480}
2481
2482MCStreamer *llvm::createAsmStreamer(MCContext &Context,
2483 std::unique_ptr<formatted_raw_ostream> OS,
2484 bool isVerboseAsm, bool useDwarfDirectory,
2485 MCInstPrinter *IP,
2486 std::unique_ptr<MCCodeEmitter> &&CE,
2487 std::unique_ptr<MCAsmBackend> &&MAB,
2488 bool ShowInst) {
2489 return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
2490 useDwarfDirectory, IP, std::move(CE), std::move(MAB),
2491 ShowInst);
2492}