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