1 | //===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===// |
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/MC/MCStreamer.h" |
10 | #include "llvm/ADT/SmallString.h" |
11 | #include "llvm/ADT/StringRef.h" |
12 | #include "llvm/ADT/Twine.h" |
13 | #include "llvm/BinaryFormat/COFF.h" |
14 | #include "llvm/BinaryFormat/MachO.h" |
15 | #include "llvm/DebugInfo/CodeView/SymbolRecord.h" |
16 | #include "llvm/MC/MCAsmBackend.h" |
17 | #include "llvm/MC/MCAsmInfo.h" |
18 | #include "llvm/MC/MCCodeView.h" |
19 | #include "llvm/MC/MCContext.h" |
20 | #include "llvm/MC/MCDwarf.h" |
21 | #include "llvm/MC/MCExpr.h" |
22 | #include "llvm/MC/MCInst.h" |
23 | #include "llvm/MC/MCInstPrinter.h" |
24 | #include "llvm/MC/MCObjectFileInfo.h" |
25 | #include "llvm/MC/MCPseudoProbe.h" |
26 | #include "llvm/MC/MCRegister.h" |
27 | #include "llvm/MC/MCRegisterInfo.h" |
28 | #include "llvm/MC/MCSection.h" |
29 | #include "llvm/MC/MCSectionCOFF.h" |
30 | #include "llvm/MC/MCSymbol.h" |
31 | #include "llvm/MC/MCWin64EH.h" |
32 | #include "llvm/MC/MCWinEH.h" |
33 | #include "llvm/Support/Casting.h" |
34 | #include "llvm/Support/ErrorHandling.h" |
35 | #include "llvm/Support/LEB128.h" |
36 | #include "llvm/Support/MathExtras.h" |
37 | #include "llvm/Support/raw_ostream.h" |
38 | #include <cassert> |
39 | #include <cstdint> |
40 | #include <cstdlib> |
41 | #include <optional> |
42 | #include <utility> |
43 | |
44 | using namespace llvm; |
45 | |
46 | MCTargetStreamer::MCTargetStreamer(MCStreamer &S) : Streamer(S) { |
47 | S.setTargetStreamer(this); |
48 | } |
49 | |
50 | // Pin the vtables to this file. |
51 | MCTargetStreamer::~MCTargetStreamer() = default; |
52 | |
53 | void MCTargetStreamer::emitLabel(MCSymbol *Symbol) {} |
54 | |
55 | void MCTargetStreamer::finish() {} |
56 | |
57 | void MCTargetStreamer::emitConstantPools() {} |
58 | |
59 | void MCTargetStreamer::changeSection(const MCSection *CurSection, |
60 | MCSection *Section, uint32_t Subsection, |
61 | raw_ostream &OS) { |
62 | Section->printSwitchToSection(MAI: *Streamer.getContext().getAsmInfo(), |
63 | T: Streamer.getContext().getTargetTriple(), OS, |
64 | Subsection); |
65 | } |
66 | |
67 | void MCTargetStreamer::emitDwarfFileDirective(StringRef Directive) { |
68 | Streamer.emitRawText(String: Directive); |
69 | } |
70 | |
71 | void MCTargetStreamer::emitValue(const MCExpr *Value) { |
72 | SmallString<128> Str; |
73 | raw_svector_ostream OS(Str); |
74 | |
75 | Streamer.getContext().getAsmInfo()->printExpr(OS, *Value); |
76 | Streamer.emitRawText(String: OS.str()); |
77 | } |
78 | |
79 | void MCTargetStreamer::emitRawBytes(StringRef Data) { |
80 | const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo(); |
81 | const char *Directive = MAI->getData8bitsDirective(); |
82 | for (const unsigned char C : Data.bytes()) { |
83 | SmallString<128> Str; |
84 | raw_svector_ostream OS(Str); |
85 | |
86 | OS << Directive << (unsigned)C; |
87 | Streamer.emitRawText(String: OS.str()); |
88 | } |
89 | } |
90 | |
91 | void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} |
92 | |
93 | MCStreamer::MCStreamer(MCContext &Ctx) |
94 | : Context(Ctx), CurrentWinFrameInfo(nullptr), |
95 | CurrentProcWinFrameInfoStartIndex(0) { |
96 | SectionStack.push_back(Elt: std::pair<MCSectionSubPair, MCSectionSubPair>()); |
97 | } |
98 | |
99 | MCStreamer::~MCStreamer() = default; |
100 | |
101 | void MCStreamer::reset() { |
102 | DwarfFrameInfos.clear(); |
103 | CurrentWinFrameInfo = nullptr; |
104 | WinFrameInfos.clear(); |
105 | SectionStack.clear(); |
106 | SectionStack.push_back(Elt: std::pair<MCSectionSubPair, MCSectionSubPair>()); |
107 | CurFrag = nullptr; |
108 | } |
109 | |
110 | raw_ostream &MCStreamer::() { |
111 | // By default, discard comments. |
112 | return nulls(); |
113 | } |
114 | |
115 | unsigned MCStreamer::getNumFrameInfos() { return DwarfFrameInfos.size(); } |
116 | ArrayRef<MCDwarfFrameInfo> MCStreamer::getDwarfFrameInfos() const { |
117 | return DwarfFrameInfos; |
118 | } |
119 | |
120 | void MCStreamer::(const Twine &T, bool TabPrefix) {} |
121 | |
122 | void MCStreamer::(const Twine &T) {} |
123 | void MCStreamer::() {} |
124 | |
125 | void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) { |
126 | for (auto &FI : DwarfFrameInfos) |
127 | FI.CompactUnwindEncoding = |
128 | (MAB ? MAB->generateCompactUnwindEncoding(FI: &FI, Ctxt: &Context) : 0); |
129 | } |
130 | |
131 | /// EmitIntValue - Special case of EmitValue that avoids the client having to |
132 | /// pass in a MCExpr for constant integers. |
133 | void MCStreamer::emitIntValue(uint64_t Value, unsigned Size) { |
134 | assert(1 <= Size && Size <= 8 && "Invalid size" ); |
135 | assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) && |
136 | "Invalid size" ); |
137 | const bool IsLittleEndian = Context.getAsmInfo()->isLittleEndian(); |
138 | uint64_t Swapped = support::endian::byte_swap( |
139 | value: Value, endian: IsLittleEndian ? llvm::endianness::little : llvm::endianness::big); |
140 | unsigned Index = IsLittleEndian ? 0 : 8 - Size; |
141 | emitBytes(Data: StringRef(reinterpret_cast<char *>(&Swapped) + Index, Size)); |
142 | } |
143 | void MCStreamer::emitIntValue(const APInt &Value) { |
144 | if (Value.getNumWords() == 1) { |
145 | emitIntValue(Value: Value.getLimitedValue(), Size: Value.getBitWidth() / 8); |
146 | return; |
147 | } |
148 | |
149 | const bool IsLittleEndianTarget = Context.getAsmInfo()->isLittleEndian(); |
150 | const bool ShouldSwap = sys::IsLittleEndianHost != IsLittleEndianTarget; |
151 | const APInt Swapped = ShouldSwap ? Value.byteSwap() : Value; |
152 | const unsigned Size = Value.getBitWidth() / 8; |
153 | SmallString<10> Tmp; |
154 | Tmp.resize(N: Size); |
155 | StoreIntToMemory(IntVal: Swapped, Dst: reinterpret_cast<uint8_t *>(Tmp.data()), StoreBytes: Size); |
156 | emitBytes(Data: Tmp.str()); |
157 | } |
158 | |
159 | /// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the |
160 | /// client having to pass in a MCExpr for constant integers. |
161 | unsigned MCStreamer::emitULEB128IntValue(uint64_t Value, unsigned PadTo) { |
162 | SmallString<128> Tmp; |
163 | raw_svector_ostream OSE(Tmp); |
164 | encodeULEB128(Value, OS&: OSE, PadTo); |
165 | emitBytes(Data: OSE.str()); |
166 | return Tmp.size(); |
167 | } |
168 | |
169 | /// EmitSLEB128IntValue - Special case of EmitSLEB128Value that avoids the |
170 | /// client having to pass in a MCExpr for constant integers. |
171 | unsigned MCStreamer::emitSLEB128IntValue(int64_t Value) { |
172 | SmallString<128> Tmp; |
173 | raw_svector_ostream OSE(Tmp); |
174 | encodeSLEB128(Value, OS&: OSE); |
175 | emitBytes(Data: OSE.str()); |
176 | return Tmp.size(); |
177 | } |
178 | |
179 | void MCStreamer::emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc) { |
180 | emitValueImpl(Value, Size, Loc); |
181 | } |
182 | |
183 | void MCStreamer::emitSymbolValue(const MCSymbol *Sym, unsigned Size, |
184 | bool IsSectionRelative) { |
185 | assert((!IsSectionRelative || Size == 4) && |
186 | "SectionRelative value requires 4-bytes" ); |
187 | |
188 | if (!IsSectionRelative) |
189 | emitValueImpl(Value: MCSymbolRefExpr::create(Symbol: Sym, Ctx&: getContext()), Size); |
190 | else |
191 | emitCOFFSecRel32(Symbol: Sym, /*Offset=*/0); |
192 | } |
193 | |
194 | /// Emit NumBytes bytes worth of the value specified by FillValue. |
195 | /// This implements directives such as '.space'. |
196 | void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) { |
197 | if (NumBytes) |
198 | emitFill(NumBytes: *MCConstantExpr::create(Value: NumBytes, Ctx&: getContext()), FillValue); |
199 | } |
200 | |
201 | void llvm::MCStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLen, |
202 | llvm::SMLoc, const MCSubtargetInfo& STI) {} |
203 | |
204 | /// The implementation in this class just redirects to emitFill. |
205 | void MCStreamer::emitZeros(uint64_t NumBytes) { emitFill(NumBytes, FillValue: 0); } |
206 | |
207 | Expected<unsigned> MCStreamer::tryEmitDwarfFileDirective( |
208 | unsigned FileNo, StringRef Directory, StringRef Filename, |
209 | std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source, |
210 | unsigned CUID) { |
211 | return getContext().getDwarfFile(Directory, FileName: Filename, FileNumber: FileNo, Checksum, |
212 | Source, CUID); |
213 | } |
214 | |
215 | void MCStreamer::emitDwarfFile0Directive(StringRef Directory, |
216 | StringRef Filename, |
217 | std::optional<MD5::MD5Result> Checksum, |
218 | std::optional<StringRef> Source, |
219 | unsigned CUID) { |
220 | getContext().setMCLineTableRootFile(CUID, CompilationDir: Directory, Filename, Checksum, |
221 | Source); |
222 | } |
223 | |
224 | void MCStreamer::emitCFIBKeyFrame() { |
225 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
226 | if (!CurFrame) |
227 | return; |
228 | CurFrame->IsBKeyFrame = true; |
229 | } |
230 | |
231 | void MCStreamer::emitCFIMTETaggedFrame() { |
232 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
233 | if (!CurFrame) |
234 | return; |
235 | CurFrame->IsMTETaggedFrame = true; |
236 | } |
237 | |
238 | void MCStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line, |
239 | unsigned Column, unsigned Flags, |
240 | unsigned Isa, unsigned Discriminator, |
241 | StringRef FileName, StringRef ) { |
242 | getContext().setCurrentDwarfLoc(FileNum: FileNo, Line, Column, Flags, Isa, |
243 | Discriminator); |
244 | } |
245 | |
246 | void MCStreamer::emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name) { |
247 | getContext() |
248 | .getMCDwarfLineTable(CUID: getContext().getDwarfCompileUnitID()) |
249 | .endCurrentSeqAndEmitLineStreamLabel(MCOS: this, DefLoc: Loc, Name); |
250 | } |
251 | |
252 | MCSymbol *MCStreamer::getDwarfLineTableSymbol(unsigned CUID) { |
253 | MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); |
254 | if (!Table.getLabel()) { |
255 | StringRef Prefix = Context.getAsmInfo()->getPrivateGlobalPrefix(); |
256 | Table.setLabel( |
257 | Context.getOrCreateSymbol(Name: Prefix + "line_table_start" + Twine(CUID))); |
258 | } |
259 | return Table.getLabel(); |
260 | } |
261 | |
262 | bool MCStreamer::hasUnfinishedDwarfFrameInfo() { |
263 | return !FrameInfoStack.empty(); |
264 | } |
265 | |
266 | MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() { |
267 | if (!hasUnfinishedDwarfFrameInfo()) { |
268 | getContext().reportError(L: getStartTokLoc(), |
269 | Msg: "this directive must appear between " |
270 | ".cfi_startproc and .cfi_endproc directives" ); |
271 | return nullptr; |
272 | } |
273 | return &DwarfFrameInfos[FrameInfoStack.back().first]; |
274 | } |
275 | |
276 | bool MCStreamer::emitCVFileDirective(unsigned FileNo, StringRef Filename, |
277 | ArrayRef<uint8_t> Checksum, |
278 | unsigned ChecksumKind) { |
279 | return getContext().getCVContext().addFile(OS&: *this, FileNumber: FileNo, Filename, ChecksumBytes: Checksum, |
280 | ChecksumKind); |
281 | } |
282 | |
283 | bool MCStreamer::emitCVFuncIdDirective(unsigned FunctionId) { |
284 | return getContext().getCVContext().recordFunctionId(FuncId: FunctionId); |
285 | } |
286 | |
287 | bool MCStreamer::emitCVInlineSiteIdDirective(unsigned FunctionId, |
288 | unsigned IAFunc, unsigned IAFile, |
289 | unsigned IALine, unsigned IACol, |
290 | SMLoc Loc) { |
291 | if (getContext().getCVContext().getCVFunctionInfo(FuncId: IAFunc) == nullptr) { |
292 | getContext().reportError(L: Loc, Msg: "parent function id not introduced by " |
293 | ".cv_func_id or .cv_inline_site_id" ); |
294 | return true; |
295 | } |
296 | |
297 | return getContext().getCVContext().recordInlinedCallSiteId( |
298 | FuncId: FunctionId, IAFunc, IAFile, IALine, IACol); |
299 | } |
300 | |
301 | void MCStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo, |
302 | unsigned Line, unsigned Column, |
303 | bool PrologueEnd, bool IsStmt, |
304 | StringRef FileName, SMLoc Loc) {} |
305 | |
306 | bool MCStreamer::checkCVLocSection(unsigned FuncId, unsigned FileNo, |
307 | SMLoc Loc) { |
308 | CodeViewContext &CVC = getContext().getCVContext(); |
309 | MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FuncId); |
310 | if (!FI) { |
311 | getContext().reportError( |
312 | L: Loc, Msg: "function id not introduced by .cv_func_id or .cv_inline_site_id" ); |
313 | return false; |
314 | } |
315 | |
316 | // Track the section |
317 | if (FI->Section == nullptr) |
318 | FI->Section = getCurrentSectionOnly(); |
319 | else if (FI->Section != getCurrentSectionOnly()) { |
320 | getContext().reportError( |
321 | L: Loc, |
322 | Msg: "all .cv_loc directives for a function must be in the same section" ); |
323 | return false; |
324 | } |
325 | return true; |
326 | } |
327 | |
328 | void MCStreamer::emitCVLinetableDirective(unsigned FunctionId, |
329 | const MCSymbol *Begin, |
330 | const MCSymbol *End) {} |
331 | |
332 | void MCStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId, |
333 | unsigned SourceFileId, |
334 | unsigned SourceLineNum, |
335 | const MCSymbol *FnStartSym, |
336 | const MCSymbol *FnEndSym) {} |
337 | |
338 | /// Only call this on endian-specific types like ulittle16_t and little32_t, or |
339 | /// structs composed of them. |
340 | template <typename T> |
341 | static void copyBytesForDefRange(SmallString<20> &BytePrefix, |
342 | codeview::SymbolKind SymKind, |
343 | const T &) { |
344 | BytePrefix.resize(N: 2 + sizeof(T)); |
345 | codeview::ulittle16_t SymKindLE = codeview::ulittle16_t(SymKind); |
346 | memcpy(dest: &BytePrefix[0], src: &SymKindLE, n: 2); |
347 | memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T)); |
348 | } |
349 | |
350 | void MCStreamer::emitCVDefRangeDirective( |
351 | ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, |
352 | StringRef FixedSizePortion) {} |
353 | |
354 | void MCStreamer::( |
355 | ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, |
356 | codeview::DefRangeRegisterRelHeader DRHdr) { |
357 | SmallString<20> BytePrefix; |
358 | copyBytesForDefRange(BytePrefix, SymKind: codeview::S_DEFRANGE_REGISTER_REL, DefRangeHeader: DRHdr); |
359 | emitCVDefRangeDirective(Ranges, FixedSizePortion: BytePrefix); |
360 | } |
361 | |
362 | void MCStreamer::( |
363 | ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, |
364 | codeview::DefRangeSubfieldRegisterHeader DRHdr) { |
365 | SmallString<20> BytePrefix; |
366 | copyBytesForDefRange(BytePrefix, SymKind: codeview::S_DEFRANGE_SUBFIELD_REGISTER, |
367 | DefRangeHeader: DRHdr); |
368 | emitCVDefRangeDirective(Ranges, FixedSizePortion: BytePrefix); |
369 | } |
370 | |
371 | void MCStreamer::( |
372 | ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, |
373 | codeview::DefRangeRegisterHeader DRHdr) { |
374 | SmallString<20> BytePrefix; |
375 | copyBytesForDefRange(BytePrefix, SymKind: codeview::S_DEFRANGE_REGISTER, DefRangeHeader: DRHdr); |
376 | emitCVDefRangeDirective(Ranges, FixedSizePortion: BytePrefix); |
377 | } |
378 | |
379 | void MCStreamer::( |
380 | ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, |
381 | codeview::DefRangeFramePointerRelHeader DRHdr) { |
382 | SmallString<20> BytePrefix; |
383 | copyBytesForDefRange(BytePrefix, SymKind: codeview::S_DEFRANGE_FRAMEPOINTER_REL, |
384 | DefRangeHeader: DRHdr); |
385 | emitCVDefRangeDirective(Ranges, FixedSizePortion: BytePrefix); |
386 | } |
387 | |
388 | void MCStreamer::emitEHSymAttributes(const MCSymbol *Symbol, |
389 | MCSymbol *EHSymbol) { |
390 | } |
391 | |
392 | void MCStreamer::initSections(bool NoExecStack, const MCSubtargetInfo &STI) { |
393 | switchSectionNoPrint(Section: getContext().getObjectFileInfo()->getTextSection()); |
394 | } |
395 | |
396 | void MCStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { |
397 | Symbol->redefineIfPossible(); |
398 | |
399 | if (!Symbol->isUndefined() || Symbol->isVariable()) |
400 | return getContext().reportError(L: Loc, Msg: "symbol '" + Twine(Symbol->getName()) + |
401 | "' is already defined" ); |
402 | |
403 | assert(!Symbol->isVariable() && "Cannot emit a variable symbol!" ); |
404 | assert(getCurrentSectionOnly() && "Cannot emit before setting section!" ); |
405 | assert(!Symbol->getFragment() && "Unexpected fragment on symbol data!" ); |
406 | assert(Symbol->isUndefined() && "Cannot define a symbol twice!" ); |
407 | |
408 | Symbol->setFragment(&getCurrentSectionOnly()->getDummyFragment()); |
409 | |
410 | MCTargetStreamer *TS = getTargetStreamer(); |
411 | if (TS) |
412 | TS->emitLabel(Symbol); |
413 | } |
414 | |
415 | void MCStreamer::emitConditionalAssignment(MCSymbol *Symbol, |
416 | const MCExpr *Value) {} |
417 | |
418 | void MCStreamer::emitCFISections(bool EH, bool Debug) {} |
419 | |
420 | void MCStreamer::emitCFIStartProc(bool IsSimple, SMLoc Loc) { |
421 | if (!FrameInfoStack.empty() && |
422 | getCurrentSectionOnly() == FrameInfoStack.back().second) |
423 | return getContext().reportError( |
424 | L: Loc, Msg: "starting new .cfi frame before finishing the previous one" ); |
425 | |
426 | MCDwarfFrameInfo Frame; |
427 | Frame.IsSimple = IsSimple; |
428 | emitCFIStartProcImpl(Frame); |
429 | |
430 | const MCAsmInfo* MAI = Context.getAsmInfo(); |
431 | if (MAI) { |
432 | for (const MCCFIInstruction& Inst : MAI->getInitialFrameState()) { |
433 | if (Inst.getOperation() == MCCFIInstruction::OpDefCfa || |
434 | Inst.getOperation() == MCCFIInstruction::OpDefCfaRegister || |
435 | Inst.getOperation() == MCCFIInstruction::OpLLVMDefAspaceCfa) { |
436 | Frame.CurrentCfaRegister = Inst.getRegister(); |
437 | } |
438 | } |
439 | } |
440 | |
441 | FrameInfoStack.emplace_back(Args: DwarfFrameInfos.size(), Args: getCurrentSectionOnly()); |
442 | DwarfFrameInfos.push_back(x: std::move(Frame)); |
443 | } |
444 | |
445 | void MCStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { |
446 | } |
447 | |
448 | void MCStreamer::emitCFIEndProc() { |
449 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
450 | if (!CurFrame) |
451 | return; |
452 | emitCFIEndProcImpl(CurFrame&: *CurFrame); |
453 | FrameInfoStack.pop_back(); |
454 | } |
455 | |
456 | void MCStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { |
457 | // Put a dummy non-null value in Frame.End to mark that this frame has been |
458 | // closed. |
459 | Frame.End = (MCSymbol *)1; |
460 | } |
461 | |
462 | MCSymbol *MCStreamer::emitLineTableLabel() { |
463 | // Create a label and insert it into the line table and return this label |
464 | const MCDwarfLoc &DwarfLoc = getContext().getCurrentDwarfLoc(); |
465 | |
466 | MCSymbol *LineStreamLabel = getContext().createTempSymbol(); |
467 | MCDwarfLineEntry LabelLineEntry(nullptr, DwarfLoc, LineStreamLabel); |
468 | getContext() |
469 | .getMCDwarfLineTable(CUID: getContext().getDwarfCompileUnitID()) |
470 | .getMCLineSections() |
471 | .addLineEntry(LineEntry: LabelLineEntry, Sec: getCurrentSectionOnly() /*Section*/); |
472 | |
473 | return LineStreamLabel; |
474 | } |
475 | |
476 | MCSymbol *MCStreamer::emitCFILabel() { |
477 | // Return a dummy non-null value so that label fields appear filled in when |
478 | // generating textual assembly. |
479 | return (MCSymbol *)1; |
480 | } |
481 | |
482 | void MCStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) { |
483 | MCSymbol *Label = emitCFILabel(); |
484 | MCCFIInstruction Instruction = |
485 | MCCFIInstruction::cfiDefCfa(L: Label, Register, Offset, Loc); |
486 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
487 | if (!CurFrame) |
488 | return; |
489 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
490 | CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register); |
491 | } |
492 | |
493 | void MCStreamer::emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) { |
494 | MCSymbol *Label = emitCFILabel(); |
495 | MCCFIInstruction Instruction = |
496 | MCCFIInstruction::cfiDefCfaOffset(L: Label, Offset); |
497 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
498 | if (!CurFrame) |
499 | return; |
500 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
501 | } |
502 | |
503 | void MCStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment, SMLoc Loc) { |
504 | MCSymbol *Label = emitCFILabel(); |
505 | MCCFIInstruction Instruction = |
506 | MCCFIInstruction::createAdjustCfaOffset(L: Label, Adjustment, Loc); |
507 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
508 | if (!CurFrame) |
509 | return; |
510 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
511 | } |
512 | |
513 | void MCStreamer::emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) { |
514 | MCSymbol *Label = emitCFILabel(); |
515 | MCCFIInstruction Instruction = |
516 | MCCFIInstruction::createDefCfaRegister(L: Label, Register, Loc); |
517 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
518 | if (!CurFrame) |
519 | return; |
520 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
521 | CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register); |
522 | } |
523 | |
524 | void MCStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset, |
525 | int64_t AddressSpace, SMLoc Loc) { |
526 | MCSymbol *Label = emitCFILabel(); |
527 | MCCFIInstruction Instruction = MCCFIInstruction::createLLVMDefAspaceCfa( |
528 | L: Label, Register, Offset, AddressSpace, Loc); |
529 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
530 | if (!CurFrame) |
531 | return; |
532 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
533 | CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register); |
534 | } |
535 | |
536 | void MCStreamer::emitCFIOffset(int64_t Register, int64_t Offset, SMLoc Loc) { |
537 | MCSymbol *Label = emitCFILabel(); |
538 | MCCFIInstruction Instruction = |
539 | MCCFIInstruction::createOffset(L: Label, Register, Offset, Loc); |
540 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
541 | if (!CurFrame) |
542 | return; |
543 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
544 | } |
545 | |
546 | void MCStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset, SMLoc Loc) { |
547 | MCSymbol *Label = emitCFILabel(); |
548 | MCCFIInstruction Instruction = |
549 | MCCFIInstruction::createRelOffset(L: Label, Register, Offset, Loc); |
550 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
551 | if (!CurFrame) |
552 | return; |
553 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
554 | } |
555 | |
556 | void MCStreamer::emitCFIPersonality(const MCSymbol *Sym, |
557 | unsigned Encoding) { |
558 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
559 | if (!CurFrame) |
560 | return; |
561 | CurFrame->Personality = Sym; |
562 | CurFrame->PersonalityEncoding = Encoding; |
563 | } |
564 | |
565 | void MCStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) { |
566 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
567 | if (!CurFrame) |
568 | return; |
569 | CurFrame->Lsda = Sym; |
570 | CurFrame->LsdaEncoding = Encoding; |
571 | } |
572 | |
573 | void MCStreamer::emitCFIRememberState(SMLoc Loc) { |
574 | MCSymbol *Label = emitCFILabel(); |
575 | MCCFIInstruction Instruction = |
576 | MCCFIInstruction::createRememberState(L: Label, Loc); |
577 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
578 | if (!CurFrame) |
579 | return; |
580 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
581 | } |
582 | |
583 | void MCStreamer::emitCFIRestoreState(SMLoc Loc) { |
584 | // FIXME: Error if there is no matching cfi_remember_state. |
585 | MCSymbol *Label = emitCFILabel(); |
586 | MCCFIInstruction Instruction = |
587 | MCCFIInstruction::createRestoreState(L: Label, Loc); |
588 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
589 | if (!CurFrame) |
590 | return; |
591 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
592 | } |
593 | |
594 | void MCStreamer::emitCFISameValue(int64_t Register, SMLoc Loc) { |
595 | MCSymbol *Label = emitCFILabel(); |
596 | MCCFIInstruction Instruction = |
597 | MCCFIInstruction::createSameValue(L: Label, Register, Loc); |
598 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
599 | if (!CurFrame) |
600 | return; |
601 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
602 | } |
603 | |
604 | void MCStreamer::emitCFIRestore(int64_t Register, SMLoc Loc) { |
605 | MCSymbol *Label = emitCFILabel(); |
606 | MCCFIInstruction Instruction = |
607 | MCCFIInstruction::createRestore(L: Label, Register, Loc); |
608 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
609 | if (!CurFrame) |
610 | return; |
611 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
612 | } |
613 | |
614 | void MCStreamer::emitCFIEscape(StringRef Values, SMLoc Loc) { |
615 | MCSymbol *Label = emitCFILabel(); |
616 | MCCFIInstruction Instruction = |
617 | MCCFIInstruction::createEscape(L: Label, Vals: Values, Loc, Comment: "" ); |
618 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
619 | if (!CurFrame) |
620 | return; |
621 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
622 | } |
623 | |
624 | void MCStreamer::emitCFIGnuArgsSize(int64_t Size, SMLoc Loc) { |
625 | MCSymbol *Label = emitCFILabel(); |
626 | MCCFIInstruction Instruction = |
627 | MCCFIInstruction::createGnuArgsSize(L: Label, Size, Loc); |
628 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
629 | if (!CurFrame) |
630 | return; |
631 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
632 | } |
633 | |
634 | void MCStreamer::emitCFISignalFrame() { |
635 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
636 | if (!CurFrame) |
637 | return; |
638 | CurFrame->IsSignalFrame = true; |
639 | } |
640 | |
641 | void MCStreamer::emitCFIUndefined(int64_t Register, SMLoc Loc) { |
642 | MCSymbol *Label = emitCFILabel(); |
643 | MCCFIInstruction Instruction = |
644 | MCCFIInstruction::createUndefined(L: Label, Register, Loc); |
645 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
646 | if (!CurFrame) |
647 | return; |
648 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
649 | } |
650 | |
651 | void MCStreamer::emitCFIRegister(int64_t Register1, int64_t Register2, |
652 | SMLoc Loc) { |
653 | MCSymbol *Label = emitCFILabel(); |
654 | MCCFIInstruction Instruction = |
655 | MCCFIInstruction::createRegister(L: Label, Register1, Register2, Loc); |
656 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
657 | if (!CurFrame) |
658 | return; |
659 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
660 | } |
661 | |
662 | void MCStreamer::emitCFIWindowSave(SMLoc Loc) { |
663 | MCSymbol *Label = emitCFILabel(); |
664 | MCCFIInstruction Instruction = MCCFIInstruction::createWindowSave(L: Label, Loc); |
665 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
666 | if (!CurFrame) |
667 | return; |
668 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
669 | } |
670 | |
671 | void MCStreamer::emitCFINegateRAState(SMLoc Loc) { |
672 | MCSymbol *Label = emitCFILabel(); |
673 | MCCFIInstruction Instruction = |
674 | MCCFIInstruction::createNegateRAState(L: Label, Loc); |
675 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
676 | if (!CurFrame) |
677 | return; |
678 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
679 | } |
680 | |
681 | void MCStreamer::emitCFINegateRAStateWithPC(SMLoc Loc) { |
682 | MCSymbol *Label = emitCFILabel(); |
683 | MCCFIInstruction Instruction = |
684 | MCCFIInstruction::createNegateRAStateWithPC(L: Label, Loc); |
685 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
686 | if (!CurFrame) |
687 | return; |
688 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
689 | } |
690 | |
691 | void MCStreamer::emitCFIReturnColumn(int64_t Register) { |
692 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
693 | if (!CurFrame) |
694 | return; |
695 | CurFrame->RAReg = Register; |
696 | } |
697 | |
698 | void MCStreamer::emitCFILabelDirective(SMLoc Loc, StringRef Name) { |
699 | MCSymbol *Label = emitCFILabel(); |
700 | MCSymbol *Sym = getContext().getOrCreateSymbol(Name); |
701 | if (MCDwarfFrameInfo *F = getCurrentDwarfFrameInfo()) |
702 | F->Instructions.push_back(x: MCCFIInstruction::createLabel(L: Label, CfiLabel: Sym, Loc)); |
703 | } |
704 | |
705 | void MCStreamer::emitCFIValOffset(int64_t Register, int64_t Offset, SMLoc Loc) { |
706 | MCSymbol *Label = emitCFILabel(); |
707 | MCCFIInstruction Instruction = |
708 | MCCFIInstruction::createValOffset(L: Label, Register, Offset, Loc); |
709 | MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); |
710 | if (!CurFrame) |
711 | return; |
712 | CurFrame->Instructions.push_back(x: std::move(Instruction)); |
713 | } |
714 | |
715 | WinEH::FrameInfo *MCStreamer::EnsureValidWinFrameInfo(SMLoc Loc) { |
716 | const MCAsmInfo *MAI = Context.getAsmInfo(); |
717 | if (!MAI->usesWindowsCFI()) { |
718 | getContext().reportError( |
719 | L: Loc, Msg: ".seh_* directives are not supported on this target" ); |
720 | return nullptr; |
721 | } |
722 | if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) { |
723 | getContext().reportError( |
724 | L: Loc, Msg: ".seh_ directive must appear within an active frame" ); |
725 | return nullptr; |
726 | } |
727 | return CurrentWinFrameInfo; |
728 | } |
729 | |
730 | void MCStreamer::emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) { |
731 | const MCAsmInfo *MAI = Context.getAsmInfo(); |
732 | if (!MAI->usesWindowsCFI()) |
733 | return getContext().reportError( |
734 | L: Loc, Msg: ".seh_* directives are not supported on this target" ); |
735 | if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End) |
736 | getContext().reportError( |
737 | L: Loc, Msg: "Starting a function before ending the previous one!" ); |
738 | |
739 | MCSymbol *StartProc = emitCFILabel(); |
740 | |
741 | CurrentProcWinFrameInfoStartIndex = WinFrameInfos.size(); |
742 | WinFrameInfos.emplace_back( |
743 | args: std::make_unique<WinEH::FrameInfo>(args&: Symbol, args&: StartProc)); |
744 | CurrentWinFrameInfo = WinFrameInfos.back().get(); |
745 | CurrentWinFrameInfo->TextSection = getCurrentSectionOnly(); |
746 | CurrentWinFrameInfo->FunctionLoc = Loc; |
747 | } |
748 | |
749 | void MCStreamer::emitWinCFIEndProc(SMLoc Loc) { |
750 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
751 | if (!CurFrame) |
752 | return; |
753 | if (CurFrame->ChainedParent) |
754 | getContext().reportError(L: Loc, Msg: "Not all chained regions terminated!" ); |
755 | |
756 | MCSymbol *Label = emitCFILabel(); |
757 | CurFrame->End = Label; |
758 | if (!CurFrame->FuncletOrFuncEnd) |
759 | CurFrame->FuncletOrFuncEnd = CurFrame->End; |
760 | |
761 | for (size_t I = CurrentProcWinFrameInfoStartIndex, E = WinFrameInfos.size(); |
762 | I != E; ++I) |
763 | emitWindowsUnwindTables(Frame: WinFrameInfos[I].get()); |
764 | switchSection(Section: CurFrame->TextSection); |
765 | } |
766 | |
767 | void MCStreamer::emitWinCFIFuncletOrFuncEnd(SMLoc Loc) { |
768 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
769 | if (!CurFrame) |
770 | return; |
771 | if (CurFrame->ChainedParent) |
772 | getContext().reportError(L: Loc, Msg: "Not all chained regions terminated!" ); |
773 | |
774 | MCSymbol *Label = emitCFILabel(); |
775 | CurFrame->FuncletOrFuncEnd = Label; |
776 | } |
777 | |
778 | void MCStreamer::emitWinCFIStartChained(SMLoc Loc) { |
779 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
780 | if (!CurFrame) |
781 | return; |
782 | |
783 | MCSymbol *StartProc = emitCFILabel(); |
784 | |
785 | WinFrameInfos.emplace_back(args: std::make_unique<WinEH::FrameInfo>( |
786 | args&: CurFrame->Function, args&: StartProc, args&: CurFrame)); |
787 | CurrentWinFrameInfo = WinFrameInfos.back().get(); |
788 | CurrentWinFrameInfo->TextSection = getCurrentSectionOnly(); |
789 | } |
790 | |
791 | void MCStreamer::emitWinCFIEndChained(SMLoc Loc) { |
792 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
793 | if (!CurFrame) |
794 | return; |
795 | if (!CurFrame->ChainedParent) |
796 | return getContext().reportError( |
797 | L: Loc, Msg: "End of a chained region outside a chained region!" ); |
798 | |
799 | MCSymbol *Label = emitCFILabel(); |
800 | |
801 | CurFrame->End = Label; |
802 | CurrentWinFrameInfo = const_cast<WinEH::FrameInfo *>(CurFrame->ChainedParent); |
803 | } |
804 | |
805 | void MCStreamer::emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except, |
806 | SMLoc Loc) { |
807 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
808 | if (!CurFrame) |
809 | return; |
810 | if (CurFrame->ChainedParent) |
811 | return getContext().reportError( |
812 | L: Loc, Msg: "Chained unwind areas can't have handlers!" ); |
813 | CurFrame->ExceptionHandler = Sym; |
814 | if (!Except && !Unwind) |
815 | getContext().reportError(L: Loc, Msg: "Don't know what kind of handler this is!" ); |
816 | if (Unwind) |
817 | CurFrame->HandlesUnwind = true; |
818 | if (Except) |
819 | CurFrame->HandlesExceptions = true; |
820 | } |
821 | |
822 | void MCStreamer::emitWinEHHandlerData(SMLoc Loc) { |
823 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
824 | if (!CurFrame) |
825 | return; |
826 | if (CurFrame->ChainedParent) |
827 | getContext().reportError(L: Loc, Msg: "Chained unwind areas can't have handlers!" ); |
828 | } |
829 | |
830 | void MCStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From, |
831 | const MCSymbolRefExpr *To, uint64_t Count) { |
832 | } |
833 | |
834 | static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID, |
835 | MCSection *MainCFISec, |
836 | const MCSection *TextSec) { |
837 | // If this is the main .text section, use the main unwind info section. |
838 | if (TextSec == Context.getObjectFileInfo()->getTextSection()) |
839 | return MainCFISec; |
840 | |
841 | const auto *TextSecCOFF = cast<MCSectionCOFF>(Val: TextSec); |
842 | auto *MainCFISecCOFF = cast<MCSectionCOFF>(Val: MainCFISec); |
843 | unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextID: NextWinCFIID); |
844 | |
845 | // If this section is COMDAT, this unwind section should be COMDAT associative |
846 | // with its group. |
847 | const MCSymbol *KeySym = nullptr; |
848 | if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { |
849 | KeySym = TextSecCOFF->getCOMDATSymbol(); |
850 | |
851 | // In a GNU environment, we can't use associative comdats. Instead, do what |
852 | // GCC does, which is to make plain comdat selectany section named like |
853 | // ".[px]data$_Z3foov". |
854 | if (!Context.getAsmInfo()->hasCOFFAssociativeComdats()) { |
855 | std::string SectionName = (MainCFISecCOFF->getName() + "$" + |
856 | TextSecCOFF->getName().split(Separator: '$').second) |
857 | .str(); |
858 | return Context.getCOFFSection(Section: SectionName, |
859 | Characteristics: MainCFISecCOFF->getCharacteristics() | |
860 | COFF::IMAGE_SCN_LNK_COMDAT, |
861 | COMDATSymName: "" , Selection: COFF::IMAGE_COMDAT_SELECT_ANY); |
862 | } |
863 | } |
864 | |
865 | return Context.getAssociativeCOFFSection(Sec: MainCFISecCOFF, KeySym, UniqueID); |
866 | } |
867 | |
868 | MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) { |
869 | return getWinCFISection(Context&: getContext(), NextWinCFIID: &NextWinCFIID, |
870 | MainCFISec: getContext().getObjectFileInfo()->getPDataSection(), |
871 | TextSec); |
872 | } |
873 | |
874 | MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) { |
875 | return getWinCFISection(Context&: getContext(), NextWinCFIID: &NextWinCFIID, |
876 | MainCFISec: getContext().getObjectFileInfo()->getXDataSection(), |
877 | TextSec); |
878 | } |
879 | |
880 | void MCStreamer::emitSyntaxDirective() {} |
881 | |
882 | static unsigned encodeSEHRegNum(MCContext &Ctx, MCRegister Reg) { |
883 | return Ctx.getRegisterInfo()->getSEHRegNum(RegNum: Reg); |
884 | } |
885 | |
886 | void MCStreamer::emitWinCFIPushReg(MCRegister Register, SMLoc Loc) { |
887 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
888 | if (!CurFrame) |
889 | return; |
890 | |
891 | MCSymbol *Label = emitCFILabel(); |
892 | |
893 | WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol( |
894 | L: Label, Reg: encodeSEHRegNum(Ctx&: Context, Reg: Register)); |
895 | CurFrame->Instructions.push_back(x: Inst); |
896 | } |
897 | |
898 | void MCStreamer::emitWinCFISetFrame(MCRegister Register, unsigned Offset, |
899 | SMLoc Loc) { |
900 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
901 | if (!CurFrame) |
902 | return; |
903 | if (CurFrame->LastFrameInst >= 0) |
904 | return getContext().reportError( |
905 | L: Loc, Msg: "frame register and offset can be set at most once" ); |
906 | if (Offset & 0x0F) |
907 | return getContext().reportError(L: Loc, Msg: "offset is not a multiple of 16" ); |
908 | if (Offset > 240) |
909 | return getContext().reportError( |
910 | L: Loc, Msg: "frame offset must be less than or equal to 240" ); |
911 | |
912 | MCSymbol *Label = emitCFILabel(); |
913 | |
914 | WinEH::Instruction Inst = Win64EH::Instruction::SetFPReg( |
915 | L: Label, Reg: encodeSEHRegNum(Ctx&: getContext(), Reg: Register), Off: Offset); |
916 | CurFrame->LastFrameInst = CurFrame->Instructions.size(); |
917 | CurFrame->Instructions.push_back(x: Inst); |
918 | } |
919 | |
920 | void MCStreamer::emitWinCFIAllocStack(unsigned Size, SMLoc Loc) { |
921 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
922 | if (!CurFrame) |
923 | return; |
924 | if (Size == 0) |
925 | return getContext().reportError(L: Loc, |
926 | Msg: "stack allocation size must be non-zero" ); |
927 | if (Size & 7) |
928 | return getContext().reportError( |
929 | L: Loc, Msg: "stack allocation size is not a multiple of 8" ); |
930 | |
931 | MCSymbol *Label = emitCFILabel(); |
932 | |
933 | WinEH::Instruction Inst = Win64EH::Instruction::Alloc(L: Label, Size); |
934 | CurFrame->Instructions.push_back(x: Inst); |
935 | } |
936 | |
937 | void MCStreamer::emitWinCFISaveReg(MCRegister Register, unsigned Offset, |
938 | SMLoc Loc) { |
939 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
940 | if (!CurFrame) |
941 | return; |
942 | |
943 | if (Offset & 7) |
944 | return getContext().reportError( |
945 | L: Loc, Msg: "register save offset is not 8 byte aligned" ); |
946 | |
947 | MCSymbol *Label = emitCFILabel(); |
948 | |
949 | WinEH::Instruction Inst = Win64EH::Instruction::SaveNonVol( |
950 | L: Label, Reg: encodeSEHRegNum(Ctx&: Context, Reg: Register), Offset); |
951 | CurFrame->Instructions.push_back(x: Inst); |
952 | } |
953 | |
954 | void MCStreamer::emitWinCFISaveXMM(MCRegister Register, unsigned Offset, |
955 | SMLoc Loc) { |
956 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
957 | if (!CurFrame) |
958 | return; |
959 | if (Offset & 0x0F) |
960 | return getContext().reportError(L: Loc, Msg: "offset is not a multiple of 16" ); |
961 | |
962 | MCSymbol *Label = emitCFILabel(); |
963 | |
964 | WinEH::Instruction Inst = Win64EH::Instruction::SaveXMM( |
965 | L: Label, Reg: encodeSEHRegNum(Ctx&: Context, Reg: Register), Offset); |
966 | CurFrame->Instructions.push_back(x: Inst); |
967 | } |
968 | |
969 | void MCStreamer::emitWinCFIPushFrame(bool Code, SMLoc Loc) { |
970 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
971 | if (!CurFrame) |
972 | return; |
973 | if (!CurFrame->Instructions.empty()) |
974 | return getContext().reportError( |
975 | L: Loc, Msg: "If present, PushMachFrame must be the first UOP" ); |
976 | |
977 | MCSymbol *Label = emitCFILabel(); |
978 | |
979 | WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(L: Label, Code); |
980 | CurFrame->Instructions.push_back(x: Inst); |
981 | } |
982 | |
983 | void MCStreamer::emitWinCFIEndProlog(SMLoc Loc) { |
984 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
985 | if (!CurFrame) |
986 | return; |
987 | |
988 | MCSymbol *Label = emitCFILabel(); |
989 | |
990 | CurFrame->PrologEnd = Label; |
991 | } |
992 | |
993 | void MCStreamer::emitWinCFIBeginEpilogue(SMLoc Loc) { |
994 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
995 | if (!CurFrame) |
996 | return; |
997 | |
998 | if (!CurFrame->PrologEnd) |
999 | return getContext().reportError( |
1000 | L: Loc, Msg: "starting epilogue (.seh_startepilogue) before prologue has ended " |
1001 | "(.seh_endprologue) in " + |
1002 | CurFrame->Function->getName()); |
1003 | |
1004 | MCSymbol *Label = emitCFILabel(); |
1005 | CurrentWinEpilog = |
1006 | &CurFrame->EpilogMap.insert_or_assign(Key: Label, Val: WinEH::FrameInfo::Epilog()) |
1007 | .first->second; |
1008 | CurrentWinEpilog->Start = Label; |
1009 | CurrentWinEpilog->Loc = Loc; |
1010 | } |
1011 | |
1012 | void MCStreamer::emitWinCFIEndEpilogue(SMLoc Loc) { |
1013 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
1014 | if (!CurFrame) |
1015 | return; |
1016 | |
1017 | if (!CurrentWinEpilog) |
1018 | return getContext().reportError(L: Loc, Msg: "Stray .seh_endepilogue in " + |
1019 | CurFrame->Function->getName()); |
1020 | |
1021 | if ((CurFrame->Version >= 2) && !CurrentWinEpilog->UnwindV2Start) |
1022 | return getContext().reportError(L: Loc, Msg: "Missing .seh_unwindv2start in " + |
1023 | CurFrame->Function->getName()); |
1024 | |
1025 | CurrentWinEpilog->End = emitCFILabel(); |
1026 | CurrentWinEpilog = nullptr; |
1027 | } |
1028 | |
1029 | void MCStreamer::emitWinCFIUnwindV2Start(SMLoc Loc) { |
1030 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
1031 | if (!CurFrame) |
1032 | return; |
1033 | |
1034 | if (!CurrentWinEpilog) |
1035 | return getContext().reportError(L: Loc, Msg: "Stray .seh_unwindv2start in " + |
1036 | CurFrame->Function->getName()); |
1037 | |
1038 | if (CurrentWinEpilog->UnwindV2Start) |
1039 | return getContext().reportError(L: Loc, Msg: "Duplicate .seh_unwindv2start in " + |
1040 | CurFrame->Function->getName()); |
1041 | |
1042 | MCSymbol *Label = emitCFILabel(); |
1043 | CurrentWinEpilog->UnwindV2Start = Label; |
1044 | } |
1045 | |
1046 | void MCStreamer::emitWinCFIUnwindVersion(uint8_t Version, SMLoc Loc) { |
1047 | WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); |
1048 | if (!CurFrame) |
1049 | return; |
1050 | |
1051 | if (CurFrame->Version != WinEH::FrameInfo::DefaultVersion) |
1052 | return getContext().reportError(L: Loc, Msg: "Duplicate .seh_unwindversion in " + |
1053 | CurFrame->Function->getName()); |
1054 | |
1055 | if (Version != 2) |
1056 | return getContext().reportError( |
1057 | L: Loc, Msg: "Unsupported version specified in .seh_unwindversion in " + |
1058 | CurFrame->Function->getName()); |
1059 | |
1060 | CurFrame->Version = Version; |
1061 | } |
1062 | |
1063 | void MCStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) {} |
1064 | |
1065 | void MCStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {} |
1066 | |
1067 | void MCStreamer::emitCOFFSectionIndex(MCSymbol const *Symbol) {} |
1068 | |
1069 | void MCStreamer::emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {} |
1070 | |
1071 | void MCStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {} |
1072 | |
1073 | void MCStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) {} |
1074 | |
1075 | void MCStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) {} |
1076 | |
1077 | /// EmitRawText - If this file is backed by an assembly streamer, this dumps |
1078 | /// the specified string in the output .s file. This capability is |
1079 | /// indicated by the hasRawTextSupport() predicate. |
1080 | void MCStreamer::emitRawTextImpl(StringRef String) { |
1081 | // This is not llvm_unreachable for the sake of out of tree backend |
1082 | // developers who may not have assembly streamers and should serve as a |
1083 | // reminder to not accidentally call EmitRawText in the absence of such. |
1084 | report_fatal_error(reason: "EmitRawText called on an MCStreamer that doesn't support " |
1085 | "it (target backend is likely missing an AsmStreamer " |
1086 | "implementation)" ); |
1087 | } |
1088 | |
1089 | void MCStreamer::emitRawText(const Twine &T) { |
1090 | SmallString<128> Str; |
1091 | emitRawTextImpl(String: T.toStringRef(Out&: Str)); |
1092 | } |
1093 | |
1094 | void MCStreamer::emitWindowsUnwindTables() {} |
1095 | |
1096 | void MCStreamer::emitWindowsUnwindTables(WinEH::FrameInfo *Frame) {} |
1097 | |
1098 | void MCStreamer::finish(SMLoc EndLoc) { |
1099 | if ((!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End) || |
1100 | (!WinFrameInfos.empty() && !WinFrameInfos.back()->End)) { |
1101 | getContext().reportError(L: EndLoc, Msg: "Unfinished frame!" ); |
1102 | return; |
1103 | } |
1104 | |
1105 | MCTargetStreamer *TS = getTargetStreamer(); |
1106 | if (TS) |
1107 | TS->finish(); |
1108 | |
1109 | finishImpl(); |
1110 | } |
1111 | |
1112 | void MCStreamer::maybeEmitDwarf64Mark() { |
1113 | if (Context.getDwarfFormat() != dwarf::DWARF64) |
1114 | return; |
1115 | AddComment(T: "DWARF64 Mark" ); |
1116 | emitInt32(Value: dwarf::DW_LENGTH_DWARF64); |
1117 | } |
1118 | |
1119 | void MCStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &) { |
1120 | assert(Context.getDwarfFormat() == dwarf::DWARF64 || |
1121 | Length <= dwarf::DW_LENGTH_lo_reserved); |
1122 | maybeEmitDwarf64Mark(); |
1123 | AddComment(T: Comment); |
1124 | emitIntValue(Value: Length, Size: dwarf::getDwarfOffsetByteSize(Format: Context.getDwarfFormat())); |
1125 | } |
1126 | |
1127 | MCSymbol *MCStreamer::emitDwarfUnitLength(const Twine &Prefix, |
1128 | const Twine &) { |
1129 | maybeEmitDwarf64Mark(); |
1130 | AddComment(T: Comment); |
1131 | MCSymbol *Lo = Context.createTempSymbol(Name: Prefix + "_start" ); |
1132 | MCSymbol *Hi = Context.createTempSymbol(Name: Prefix + "_end" ); |
1133 | |
1134 | emitAbsoluteSymbolDiff( |
1135 | Hi, Lo, Size: dwarf::getDwarfOffsetByteSize(Format: Context.getDwarfFormat())); |
1136 | // emit the begin symbol after we generate the length field. |
1137 | emitLabel(Symbol: Lo); |
1138 | // Return the Hi symbol to the caller. |
1139 | return Hi; |
1140 | } |
1141 | |
1142 | void MCStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) { |
1143 | // Set the value of the symbol, as we are at the start of the line table. |
1144 | emitLabel(Symbol: StartSym); |
1145 | } |
1146 | |
1147 | void MCStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) { |
1148 | visitUsedExpr(Expr: *Value); |
1149 | Symbol->setVariableValue(Value); |
1150 | |
1151 | MCTargetStreamer *TS = getTargetStreamer(); |
1152 | if (TS) |
1153 | TS->emitAssignment(Symbol, Value); |
1154 | } |
1155 | |
1156 | void MCTargetStreamer::prettyPrintAsm(MCInstPrinter &InstPrinter, |
1157 | uint64_t Address, const MCInst &Inst, |
1158 | const MCSubtargetInfo &STI, |
1159 | raw_ostream &OS) { |
1160 | InstPrinter.printInst(MI: &Inst, Address, Annot: "" , STI, OS); |
1161 | } |
1162 | |
1163 | void MCStreamer::visitUsedSymbol(const MCSymbol &Sym) { |
1164 | } |
1165 | |
1166 | void MCStreamer::visitUsedExpr(const MCExpr &Expr) { |
1167 | switch (Expr.getKind()) { |
1168 | case MCExpr::Target: |
1169 | cast<MCTargetExpr>(Val: Expr).visitUsedExpr(Streamer&: *this); |
1170 | break; |
1171 | |
1172 | case MCExpr::Constant: |
1173 | break; |
1174 | |
1175 | case MCExpr::Binary: { |
1176 | const MCBinaryExpr &BE = cast<MCBinaryExpr>(Val: Expr); |
1177 | visitUsedExpr(Expr: *BE.getLHS()); |
1178 | visitUsedExpr(Expr: *BE.getRHS()); |
1179 | break; |
1180 | } |
1181 | |
1182 | case MCExpr::SymbolRef: |
1183 | visitUsedSymbol(Sym: cast<MCSymbolRefExpr>(Val: Expr).getSymbol()); |
1184 | break; |
1185 | |
1186 | case MCExpr::Unary: |
1187 | visitUsedExpr(Expr: *cast<MCUnaryExpr>(Val: Expr).getSubExpr()); |
1188 | break; |
1189 | |
1190 | case MCExpr::Specifier: |
1191 | visitUsedExpr(Expr: *cast<MCSpecifierExpr>(Val: Expr).getSubExpr()); |
1192 | break; |
1193 | } |
1194 | } |
1195 | |
1196 | void MCStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &) { |
1197 | // Scan for values. |
1198 | for (unsigned i = Inst.getNumOperands(); i--;) |
1199 | if (Inst.getOperand(i).isExpr()) |
1200 | visitUsedExpr(Expr: *Inst.getOperand(i).getExpr()); |
1201 | } |
1202 | |
1203 | void MCStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type, |
1204 | uint64_t Attr, uint64_t Discriminator, |
1205 | const MCPseudoProbeInlineStack &InlineStack, |
1206 | MCSymbol *FnSym) { |
1207 | auto &Context = getContext(); |
1208 | |
1209 | // Create a symbol at in the current section for use in the probe. |
1210 | MCSymbol *ProbeSym = Context.createTempSymbol(); |
1211 | |
1212 | // Set the value of the symbol to use for the MCPseudoProbe. |
1213 | emitLabel(Symbol: ProbeSym); |
1214 | |
1215 | // Create a (local) probe entry with the symbol. |
1216 | MCPseudoProbe Probe(ProbeSym, Guid, Index, Type, Attr, Discriminator); |
1217 | |
1218 | // Add the probe entry to this section's entries. |
1219 | Context.getMCPseudoProbeTable().getProbeSections().addPseudoProbe( |
1220 | FuncSym: FnSym, Probe, InlineStack); |
1221 | } |
1222 | |
1223 | void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, |
1224 | unsigned Size) { |
1225 | // Get the Hi-Lo expression. |
1226 | const MCExpr *Diff = |
1227 | MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: Hi, Ctx&: Context), |
1228 | RHS: MCSymbolRefExpr::create(Symbol: Lo, Ctx&: Context), Ctx&: Context); |
1229 | |
1230 | const MCAsmInfo *MAI = Context.getAsmInfo(); |
1231 | if (!MAI->doesSetDirectiveSuppressReloc()) { |
1232 | emitValue(Value: Diff, Size); |
1233 | return; |
1234 | } |
1235 | |
1236 | // Otherwise, emit with .set (aka assignment). |
1237 | MCSymbol *SetLabel = Context.createTempSymbol(Name: "set" ); |
1238 | emitAssignment(Symbol: SetLabel, Value: Diff); |
1239 | emitSymbolValue(Sym: SetLabel, Size); |
1240 | } |
1241 | |
1242 | void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, |
1243 | const MCSymbol *Lo) { |
1244 | // Get the Hi-Lo expression. |
1245 | const MCExpr *Diff = |
1246 | MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: Hi, Ctx&: Context), |
1247 | RHS: MCSymbolRefExpr::create(Symbol: Lo, Ctx&: Context), Ctx&: Context); |
1248 | |
1249 | emitULEB128Value(Value: Diff); |
1250 | } |
1251 | |
1252 | void MCStreamer::emitSubsectionsViaSymbols() { |
1253 | llvm_unreachable( |
1254 | "emitSubsectionsViaSymbols only supported on Mach-O targets" ); |
1255 | } |
1256 | void MCStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} |
1257 | void MCStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) { |
1258 | llvm_unreachable("this directive only supported on COFF targets" ); |
1259 | } |
1260 | void MCStreamer::endCOFFSymbolDef() { |
1261 | llvm_unreachable("this directive only supported on COFF targets" ); |
1262 | } |
1263 | void MCStreamer::emitFileDirective(StringRef Filename) {} |
1264 | void MCStreamer::emitFileDirective(StringRef Filename, |
1265 | StringRef CompilerVersion, |
1266 | StringRef TimeStamp, StringRef Description) { |
1267 | } |
1268 | void MCStreamer::emitCOFFSymbolStorageClass(int StorageClass) { |
1269 | llvm_unreachable("this directive only supported on COFF targets" ); |
1270 | } |
1271 | void MCStreamer::emitCOFFSymbolType(int Type) { |
1272 | llvm_unreachable("this directive only supported on COFF targets" ); |
1273 | } |
1274 | void MCStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size, |
1275 | MCSymbol *CsectSym, |
1276 | Align Alignment) { |
1277 | llvm_unreachable("this directive only supported on XCOFF targets" ); |
1278 | } |
1279 | |
1280 | void MCStreamer::emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol, |
1281 | MCSymbolAttr Linkage, |
1282 | MCSymbolAttr Visibility) { |
1283 | llvm_unreachable("emitXCOFFSymbolLinkageWithVisibility is only supported on " |
1284 | "XCOFF targets" ); |
1285 | } |
1286 | |
1287 | void MCStreamer::emitXCOFFRenameDirective(const MCSymbol *Name, |
1288 | StringRef Rename) {} |
1289 | |
1290 | void MCStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) { |
1291 | llvm_unreachable("emitXCOFFRefDirective is only supported on XCOFF targets" ); |
1292 | } |
1293 | |
1294 | void MCStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol, |
1295 | const MCSymbol *Trap, |
1296 | unsigned Lang, unsigned Reason, |
1297 | unsigned FunctionSize, |
1298 | bool hasDebug) { |
1299 | report_fatal_error(reason: "emitXCOFFExceptDirective is only supported on " |
1300 | "XCOFF targets" ); |
1301 | } |
1302 | |
1303 | void MCStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) { |
1304 | llvm_unreachable("emitXCOFFCInfoSym is only supported on" |
1305 | "XCOFF targets" ); |
1306 | } |
1307 | |
1308 | void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} |
1309 | void MCStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym, |
1310 | StringRef Name, bool KeepOriginalSym) {} |
1311 | void MCStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, |
1312 | Align ByteAlignment) {} |
1313 | void MCStreamer::emitZerofill(MCSection *, MCSymbol *, uint64_t, Align, SMLoc) { |
1314 | } |
1315 | void MCStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, |
1316 | uint64_t Size, Align ByteAlignment) {} |
1317 | void MCStreamer::changeSection(MCSection *Section, uint32_t) { |
1318 | CurFrag = &Section->getDummyFragment(); |
1319 | } |
1320 | void MCStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} |
1321 | void MCStreamer::emitBytes(StringRef Data) {} |
1322 | void MCStreamer::emitBinaryData(StringRef Data) { emitBytes(Data); } |
1323 | void MCStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) { |
1324 | visitUsedExpr(Expr: *Value); |
1325 | } |
1326 | void MCStreamer::emitULEB128Value(const MCExpr *Value) {} |
1327 | void MCStreamer::emitSLEB128Value(const MCExpr *Value) {} |
1328 | void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {} |
1329 | void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, |
1330 | SMLoc Loc) {} |
1331 | void MCStreamer::emitValueToAlignment(Align Alignment, int64_t Value, |
1332 | unsigned ValueSize, |
1333 | unsigned MaxBytesToEmit) {} |
1334 | void MCStreamer::emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, |
1335 | unsigned MaxBytesToEmit) {} |
1336 | void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value, |
1337 | SMLoc Loc) {} |
1338 | void MCStreamer::emitBundleAlignMode(Align Alignment) {} |
1339 | void MCStreamer::emitBundleLock(bool AlignToEnd) {} |
1340 | void MCStreamer::finishImpl() {} |
1341 | void MCStreamer::emitBundleUnlock() {} |
1342 | |
1343 | bool MCStreamer::popSection() { |
1344 | if (SectionStack.size() <= 1) |
1345 | return false; |
1346 | auto I = SectionStack.end(); |
1347 | --I; |
1348 | MCSectionSubPair OldSec = I->first; |
1349 | --I; |
1350 | MCSectionSubPair NewSec = I->first; |
1351 | |
1352 | if (NewSec.first && OldSec != NewSec) |
1353 | changeSection(Section: NewSec.first, NewSec.second); |
1354 | SectionStack.pop_back(); |
1355 | return true; |
1356 | } |
1357 | |
1358 | void MCStreamer::switchSection(MCSection *Section, uint32_t Subsection) { |
1359 | assert(Section && "Cannot switch to a null section!" ); |
1360 | MCSectionSubPair curSection = SectionStack.back().first; |
1361 | SectionStack.back().second = curSection; |
1362 | if (MCSectionSubPair(Section, Subsection) != curSection) { |
1363 | changeSection(Section, Subsection); |
1364 | SectionStack.back().first = MCSectionSubPair(Section, Subsection); |
1365 | assert(!Section->hasEnded() && "Section already ended" ); |
1366 | MCSymbol *Sym = Section->getBeginSymbol(); |
1367 | if (Sym && !Sym->isInSection()) |
1368 | emitLabel(Symbol: Sym); |
1369 | } |
1370 | } |
1371 | |
1372 | bool MCStreamer::switchSection(MCSection *Section, const MCExpr *SubsecExpr) { |
1373 | int64_t Subsec = 0; |
1374 | if (SubsecExpr) { |
1375 | if (!SubsecExpr->evaluateAsAbsolute(Res&: Subsec, Asm: getAssemblerPtr())) { |
1376 | getContext().reportError(L: SubsecExpr->getLoc(), |
1377 | Msg: "cannot evaluate subsection number" ); |
1378 | return true; |
1379 | } |
1380 | if (!isUInt<31>(x: Subsec)) { |
1381 | getContext().reportError(L: SubsecExpr->getLoc(), |
1382 | Msg: "subsection number " + Twine(Subsec) + |
1383 | " is not within [0,2147483647]" ); |
1384 | return true; |
1385 | } |
1386 | } |
1387 | switchSection(Section, Subsection: Subsec); |
1388 | return false; |
1389 | } |
1390 | |
1391 | void MCStreamer::switchSectionNoPrint(MCSection *Section) { |
1392 | SectionStack.back().second = SectionStack.back().first; |
1393 | SectionStack.back().first = MCSectionSubPair(Section, 0); |
1394 | changeSection(Section, 0); |
1395 | MCSymbol *Sym = Section->getBeginSymbol(); |
1396 | if (Sym && !Sym->isInSection()) |
1397 | emitLabel(Symbol: Sym); |
1398 | } |
1399 | |
1400 | MCSymbol *MCStreamer::endSection(MCSection *Section) { |
1401 | // TODO: keep track of the last subsection so that this symbol appears in the |
1402 | // correct place. |
1403 | MCSymbol *Sym = Section->getEndSymbol(Ctx&: Context); |
1404 | if (Sym->isInSection()) |
1405 | return Sym; |
1406 | |
1407 | switchSection(Section); |
1408 | emitLabel(Symbol: Sym); |
1409 | return Sym; |
1410 | } |
1411 | |
1412 | static VersionTuple |
1413 | targetVersionOrMinimumSupportedOSVersion(const Triple &Target, |
1414 | VersionTuple TargetVersion) { |
1415 | VersionTuple Min = Target.getMinimumSupportedOSVersion(); |
1416 | return !Min.empty() && Min > TargetVersion ? Min : TargetVersion; |
1417 | } |
1418 | |
1419 | static MCVersionMinType |
1420 | getMachoVersionMinLoadCommandType(const Triple &Target) { |
1421 | assert(Target.isOSDarwin() && "expected a darwin OS" ); |
1422 | switch (Target.getOS()) { |
1423 | case Triple::MacOSX: |
1424 | case Triple::Darwin: |
1425 | return MCVM_OSXVersionMin; |
1426 | case Triple::IOS: |
1427 | assert(!Target.isMacCatalystEnvironment() && |
1428 | "mac Catalyst should use LC_BUILD_VERSION" ); |
1429 | return MCVM_IOSVersionMin; |
1430 | case Triple::TvOS: |
1431 | return MCVM_TvOSVersionMin; |
1432 | case Triple::WatchOS: |
1433 | return MCVM_WatchOSVersionMin; |
1434 | default: |
1435 | break; |
1436 | } |
1437 | llvm_unreachable("unexpected OS type" ); |
1438 | } |
1439 | |
1440 | static VersionTuple getMachoBuildVersionSupportedOS(const Triple &Target) { |
1441 | assert(Target.isOSDarwin() && "expected a darwin OS" ); |
1442 | switch (Target.getOS()) { |
1443 | case Triple::MacOSX: |
1444 | case Triple::Darwin: |
1445 | return VersionTuple(10, 14); |
1446 | case Triple::IOS: |
1447 | // Mac Catalyst always uses the build version load command. |
1448 | if (Target.isMacCatalystEnvironment()) |
1449 | return VersionTuple(); |
1450 | [[fallthrough]]; |
1451 | case Triple::TvOS: |
1452 | return VersionTuple(12); |
1453 | case Triple::WatchOS: |
1454 | return VersionTuple(5); |
1455 | case Triple::DriverKit: |
1456 | case Triple::BridgeOS: |
1457 | case Triple::XROS: |
1458 | // DriverKit/BridgeOS/XROS always use the build version load command. |
1459 | return VersionTuple(); |
1460 | default: |
1461 | break; |
1462 | } |
1463 | llvm_unreachable("unexpected OS type" ); |
1464 | } |
1465 | |
1466 | static MachO::PlatformType |
1467 | getMachoBuildVersionPlatformType(const Triple &Target) { |
1468 | assert(Target.isOSDarwin() && "expected a darwin OS" ); |
1469 | switch (Target.getOS()) { |
1470 | case Triple::MacOSX: |
1471 | case Triple::Darwin: |
1472 | return MachO::PLATFORM_MACOS; |
1473 | case Triple::IOS: |
1474 | if (Target.isMacCatalystEnvironment()) |
1475 | return MachO::PLATFORM_MACCATALYST; |
1476 | return Target.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR |
1477 | : MachO::PLATFORM_IOS; |
1478 | case Triple::TvOS: |
1479 | return Target.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR |
1480 | : MachO::PLATFORM_TVOS; |
1481 | case Triple::WatchOS: |
1482 | return Target.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR |
1483 | : MachO::PLATFORM_WATCHOS; |
1484 | case Triple::DriverKit: |
1485 | return MachO::PLATFORM_DRIVERKIT; |
1486 | case Triple::XROS: |
1487 | return Target.isSimulatorEnvironment() ? MachO::PLATFORM_XROS_SIMULATOR |
1488 | : MachO::PLATFORM_XROS; |
1489 | case Triple::BridgeOS: |
1490 | return MachO::PLATFORM_BRIDGEOS; |
1491 | default: |
1492 | break; |
1493 | } |
1494 | llvm_unreachable("unexpected OS type" ); |
1495 | } |
1496 | |
1497 | void MCStreamer::emitVersionForTarget( |
1498 | const Triple &Target, const VersionTuple &SDKVersion, |
1499 | const Triple *DarwinTargetVariantTriple, |
1500 | const VersionTuple &DarwinTargetVariantSDKVersion) { |
1501 | if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin()) |
1502 | return; |
1503 | // Do we even know the version? |
1504 | if (Target.getOSMajorVersion() == 0) |
1505 | return; |
1506 | |
1507 | VersionTuple Version; |
1508 | switch (Target.getOS()) { |
1509 | case Triple::MacOSX: |
1510 | case Triple::Darwin: |
1511 | Target.getMacOSXVersion(Version); |
1512 | break; |
1513 | case Triple::IOS: |
1514 | case Triple::TvOS: |
1515 | Version = Target.getiOSVersion(); |
1516 | break; |
1517 | case Triple::WatchOS: |
1518 | Version = Target.getWatchOSVersion(); |
1519 | break; |
1520 | case Triple::DriverKit: |
1521 | Version = Target.getDriverKitVersion(); |
1522 | break; |
1523 | case Triple::XROS: |
1524 | case Triple::BridgeOS: |
1525 | Version = Target.getOSVersion(); |
1526 | break; |
1527 | default: |
1528 | llvm_unreachable("unexpected OS type" ); |
1529 | } |
1530 | assert(Version.getMajor() != 0 && "A non-zero major version is expected" ); |
1531 | auto LinkedTargetVersion = |
1532 | targetVersionOrMinimumSupportedOSVersion(Target, TargetVersion: Version); |
1533 | auto BuildVersionOSVersion = getMachoBuildVersionSupportedOS(Target); |
1534 | bool ShouldEmitBuildVersion = false; |
1535 | if (BuildVersionOSVersion.empty() || |
1536 | LinkedTargetVersion >= BuildVersionOSVersion) { |
1537 | if (Target.isMacCatalystEnvironment() && DarwinTargetVariantTriple && |
1538 | DarwinTargetVariantTriple->isMacOSX()) { |
1539 | emitVersionForTarget(Target: *DarwinTargetVariantTriple, |
1540 | SDKVersion: DarwinTargetVariantSDKVersion, |
1541 | /*DarwinTargetVariantTriple=*/nullptr, |
1542 | /*DarwinTargetVariantSDKVersion=*/VersionTuple()); |
1543 | emitDarwinTargetVariantBuildVersion( |
1544 | Platform: getMachoBuildVersionPlatformType(Target), |
1545 | Major: LinkedTargetVersion.getMajor(), |
1546 | Minor: LinkedTargetVersion.getMinor().value_or(u: 0), |
1547 | Update: LinkedTargetVersion.getSubminor().value_or(u: 0), SDKVersion); |
1548 | return; |
1549 | } |
1550 | emitBuildVersion(Platform: getMachoBuildVersionPlatformType(Target), |
1551 | Major: LinkedTargetVersion.getMajor(), |
1552 | Minor: LinkedTargetVersion.getMinor().value_or(u: 0), |
1553 | Update: LinkedTargetVersion.getSubminor().value_or(u: 0), SDKVersion); |
1554 | ShouldEmitBuildVersion = true; |
1555 | } |
1556 | |
1557 | if (const Triple *TVT = DarwinTargetVariantTriple) { |
1558 | if (Target.isMacOSX() && TVT->isMacCatalystEnvironment()) { |
1559 | auto TVLinkedTargetVersion = |
1560 | targetVersionOrMinimumSupportedOSVersion(Target: *TVT, TargetVersion: TVT->getiOSVersion()); |
1561 | emitDarwinTargetVariantBuildVersion( |
1562 | Platform: getMachoBuildVersionPlatformType(Target: *TVT), |
1563 | Major: TVLinkedTargetVersion.getMajor(), |
1564 | Minor: TVLinkedTargetVersion.getMinor().value_or(u: 0), |
1565 | Update: TVLinkedTargetVersion.getSubminor().value_or(u: 0), |
1566 | SDKVersion: DarwinTargetVariantSDKVersion); |
1567 | } |
1568 | } |
1569 | |
1570 | if (ShouldEmitBuildVersion) |
1571 | return; |
1572 | |
1573 | emitVersionMin(Type: getMachoVersionMinLoadCommandType(Target), |
1574 | Major: LinkedTargetVersion.getMajor(), |
1575 | Minor: LinkedTargetVersion.getMinor().value_or(u: 0), |
1576 | Update: LinkedTargetVersion.getSubminor().value_or(u: 0), SDKVersion); |
1577 | } |
1578 | |