LLVM: lib/MC/MCMachOStreamer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
34#include
35#include
36
37namespace llvm {
42}
43
44using namespace llvm;
45
46namespace {
47
48class MCMachOStreamer : public MCObjectStreamer {
49private:
50
51
52
53 bool LabelSections;
54
55
56
57
58 DenseMap<const MCSection*, bool> HasSectionLabel;
59
61 void emitDataRegionEnd();
62
63public:
64 MCMachOStreamer(MCContext &Context, std::unique_ptr MAB,
65 std::unique_ptr OW,
66 std::unique_ptr Emitter, bool label)
67 : MCObjectStreamer(Context, std::move(MAB), std::move(OW),
69 LabelSections(label) {}
70
71
72 void reset() override {
73 HasSectionLabel.clear();
75 }
76
77 MachObjectWriter &getWriter() {
78 return static_cast<MachObjectWriter &>(getAssembler().getWriter());
79 }
80
81
82
83
84 void changeSection(MCSection *Sect, uint32_t Subsection = 0) override;
85 void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
86 void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
87 void emitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override;
88 void emitSubsectionsViaSymbols() override;
89 void emitLinkerOptions(ArrayRefstd::string Options) override;
91 void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
92 unsigned Update, VersionTuple SDKVersion) override;
93 void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
94 unsigned Update, VersionTuple SDKVersion) override;
95 void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major,
96 unsigned Minor, unsigned Update,
97 VersionTuple SDKVersion) override;
99 void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
100 void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
101 Align ByteAlignment) override;
102
103 void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
104 Align ByteAlignment) override;
105 void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
106 uint64_t Size = 0, Align ByteAlignment = Align(1),
107 SMLoc Loc = SMLoc()) override;
108 void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
109 Align ByteAlignment = Align(1)) override;
110
111 void emitIdent(StringRef IdentString) override {
113 }
114
115 void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override {
116 getWriter().getLOHContainer().addDirective(Kind, Args);
117 }
118 void emitCGProfileEntry(const MCSymbolRefExpr *From,
119 const MCSymbolRefExpr *To, uint64_t Count) override {
121 getWriter().getCGProfile().push_back({From, To, Count});
122 }
123
124 void finishImpl() override;
125
126 void finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE);
127 void finalizeCGProfile();
128 void createAddrSigSection();
129};
130
131}
132
133void MCMachOStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
135
136
137
138 if (LabelSections && !HasSectionLabel[Section] &&
139 ->getBeginSymbol()) {
141 Section->setBeginSymbol(Label);
142 HasSectionLabel[Section] = true;
143 if (->isInSection())
144 emitLabel(Label);
145 }
146}
147
148void MCMachOStreamer::emitEHSymAttributes(const MCSymbol *Symbol,
149 MCSymbol *EHSymbol) {
150 auto *Sym = static_cast<const MCSymbolMachO *>(Symbol);
151 getAssembler().registerSymbol(*Symbol);
152 if (Sym->isExternal())
153 emitSymbolAttribute(EHSymbol, MCSA_Global);
154 if (Sym->isWeakDefinition())
156 if (Sym->isPrivateExtern())
158}
159
160void MCMachOStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
161
162
164 newFragment();
165
167
168
169
170
171
172
173
174
175 static_cast<MCSymbolMachO *>(Symbol)->clearReferenceType();
176}
177
178void MCMachOStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
179 MCValue Res;
180
181 if (Value->evaluateAsRelocatable(Res, nullptr)) {
182 if (const auto *SymA = Res.getAddSym()) {
184 (SymA->getName().empty() || Res.getConstant() != 0))
185 static_cast<MCSymbolMachO *>(Symbol)->setAltEntry();
186 }
187 }
189}
190
192
194 emitLabel(Start);
195
196 getWriter().getDataRegions().push_back({Kind, Start, nullptr});
197}
198
199void MCMachOStreamer::emitDataRegionEnd() {
200 auto &Regions = getWriter().getDataRegions();
201 assert(!Regions.empty() && "Mismatched .end_data_region!");
202 auto &Data = Regions.back();
203 assert(.End && "Mismatched .end_data_region!");
204
206 emitLabel(Data.End);
207}
208
209void MCMachOStreamer::emitSubsectionsViaSymbols() {
210 getWriter().setSubsectionsViaSymbols(true);
211}
212
213void MCMachOStreamer::emitLinkerOptions(ArrayRefstd::string Options) {
214 getWriter().getLinkerOptions().push_back(Options);
215}
216
218 switch (Kind) {
220 emitDataRegion(MachO::DataRegionType::DICE_KIND_DATA);
221 return;
223 emitDataRegion(MachO::DataRegionType::DICE_KIND_JUMP_TABLE8);
224 return;
226 emitDataRegion(MachO::DataRegionType::DICE_KIND_JUMP_TABLE16);
227 return;
229 emitDataRegion(MachO::DataRegionType::DICE_KIND_JUMP_TABLE32);
230 return;
232 emitDataRegionEnd();
233 return;
234 }
235}
236
237void MCMachOStreamer::emitVersionMin(MCVersionMinType Kind, unsigned Major,
238 unsigned Minor, unsigned Update,
239 VersionTuple SDKVersion) {
240 getWriter().setVersionMin(Kind, Major, Minor, Update, SDKVersion);
241}
242
243void MCMachOStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
244 unsigned Minor, unsigned Update,
245 VersionTuple SDKVersion) {
247 Update, SDKVersion);
248}
249
250void MCMachOStreamer::emitDarwinTargetVariantBuildVersion(
251 unsigned Platform, unsigned Major, unsigned Minor, unsigned Update,
252 VersionTuple SDKVersion) {
253 getWriter().setTargetVariantBuildVersion((MachO::PlatformType)Platform, Major,
254 Minor, Update, SDKVersion);
255}
256
257bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,
259 auto *Symbol = static_cast<MCSymbolMachO *>(Sym);
260
261
262
264
265
266 getWriter().getIndirectSymbols().push_back(
267 {Symbol, getCurrentSectionOnly()});
268 return true;
269 }
270
271
272
273
274 getAssembler().registerSymbol(*Symbol);
275
276
277
278
279
280
281
302 return false;
303
305 Symbol->setExternal(true);
306
307
308
309
310
311
312 Symbol->setReferenceTypeUndefinedLazy(false);
313 break;
314
316
317 Symbol->setNoDeadStrip();
318 if (Symbol->isUndefined())
319 Symbol->setReferenceTypeUndefinedLazy(true);
320 break;
321
322
323
326 Symbol->setNoDeadStrip();
327 break;
328
330 Symbol->setSymbolResolver();
331 break;
332
334 Symbol->setAltEntry();
335 break;
336
338 Symbol->setExternal(true);
339 Symbol->setPrivateExtern(true);
340 break;
341
343
344 if (Symbol->isUndefined())
345 Symbol->setWeakReference();
346 break;
347
349
350
351 Symbol->setWeakDefinition();
352 break;
353
355 Symbol->setWeakDefinition();
356 Symbol->setWeakReference();
357 break;
358
361 break;
362 }
363
364 return true;
365}
366
367void MCMachOStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
368
369 getAssembler().registerSymbol(*Symbol);
370 static_cast<MCSymbolMachO *>(Symbol)->setDesc(DescValue);
371}
372
373void MCMachOStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
374 Align ByteAlignment) {
375 auto &Sym = static_cast<MCSymbolMachO &>(*Symbol);
376
377 assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
378
379 getAssembler().registerSymbol(Sym);
380 Sym.setExternal(true);
382}
383
384void MCMachOStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
385 Align ByteAlignment) {
386
387 return emitZerofill(getContext().getObjectFileInfo()->getDataBSSSection(),
388 Symbol, Size, ByteAlignment);
389}
390
391void MCMachOStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
392 uint64_t Size, Align ByteAlignment,
393 SMLoc Loc) {
394
395
396
397 if (->isBssSection()) {
399 Loc, "The usage of .zerofill is restricted to sections of "
400 "ZEROFILL type. Use .zero or .space instead.");
401 return;
402
403 }
404
405 pushSection();
406 switchSection(Section);
407
408
409 if (Symbol) {
410 emitValueToAlignment(ByteAlignment, 0, 1, 0);
411 emitLabel(Symbol);
412 emitZeros(Size);
413 }
414 popSection();
415}
416
417
418
419void MCMachOStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
420 uint64_t Size, Align ByteAlignment) {
421 emitZerofill(Section, Symbol, Size, ByteAlignment);
422}
423
424void MCMachOStreamer::finishImpl() {
425 emitFrames();
426
427
428
429
430
431
432 DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap;
433 for (const MCSymbol &Symbol : getAssembler().symbols()) {
434 auto &Sym = static_cast<const MCSymbolMachO &>(Symbol);
436 !Sym.isAltEntry()) {
437
439 "Invalid offset in atom defining symbol!");
440 DefiningSymbolMap[Symbol.getFragment()] = &Symbol;
441 }
442 }
443
444
445
446 for (MCSection &Sec : getAssembler()) {
447 static_cast<MCSectionMachO &>(Sec).allocAtoms();
448 const MCSymbol *CurrentAtom = nullptr;
449 size_t I = 0;
450 for (MCFragment &Frag : Sec) {
451 if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(&Frag))
452 CurrentAtom = Symbol;
453 static_cast<MCSectionMachO &>(Sec).setAtom(I++, CurrentAtom);
454 }
455 }
456
457 finalizeCGProfile();
458
459 createAddrSigSection();
461}
462
463void MCMachOStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {
464 auto *S =
465 static_cast<MCSymbolMachO *>(const_cast<MCSymbol *>(&SRE->getSymbol()));
466 if (getAssembler().registerSymbol(*S))
467 S->setExternal(true);
468}
469
470void MCMachOStreamer::finalizeCGProfile() {
471 MCAssembler &Asm = getAssembler();
472 MCObjectWriter &W = getWriter();
473 if (W.getCGProfile().empty())
474 return;
475 for (auto &E : W.getCGProfile()) {
476 finalizeCGProfileEntry(E.From);
477 finalizeCGProfileEntry(E.To);
478 }
479
480
481
482 MCSection *CGProfileSection = Asm.getContext().getMachOSection(
484
486
487 size_t SectionBytes =
488 W.getCGProfile().size() * (2 * sizeof(uint32_t) + sizeof(uint64_t));
489 (*CGProfileSection->begin())
490 .setVarContents(std::vector(SectionBytes, 0));
491}
492
494 std::unique_ptr &&MAB,
495 std::unique_ptr &&OW,
496 std::unique_ptr &&CE,
497 bool DWARFMustBeAtTheEnd,
498 bool LabelSections) {
499 return new MCMachOStreamer(Context, std::move(MAB), std::move(OW),
500 std::move(CE), LabelSections);
501}
502
503
504
505
506
507
508
509void MCMachOStreamer::createAddrSigSection() {
513 return;
514
515
517 Asm.getContext().getObjectFileInfo()->getAddrSigSection();
518
521
522
523
524
525
526 constexpr char zero[8] = {};
527 Frag->setVarContents(zero);
528}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
dxil DXContainer Global Emitter
This file defines the DenseMap class.
static bool isSymbolLinkerVisible(const MCSymbol &Symbol)
This file defines the SmallVector class.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Context object for machine code objects.
Instances of this class represent a single low-level machine instruction.
void reset() override
state management
void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override
Emit an assignment of Value to Symbol.
void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc()) override
Emit a label for Symbol into the current section.
void finishImpl() override
Streamer specific finalization.
void changeSection(MCSection *Section, uint32_t Subsection=0) override
This is called by popSection and switchSection, if the current section changes.
Defines the object file and target independent interfaces used by the assembler backend to write nati...
bool getEmitAddrsigSection()
Instances of this class represent a uniqued identifier for a section in the current translation unit.
FragList * curFragList() const
Streaming machine code generation interface.
Generic base class for all target subtargets.
const MCSymbol & getSymbol() const
void setCommon(uint64_t Size, Align Alignment)
Mark this symbol as being 'common'.
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute).
bool isVariable() const
isVariable - Check if this is a variable symbol.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
const MCSymbol * getAddSym() const
int64_t getConstant() const
const MCSymbol * getSubSym() const
static SectionKind getMetadata()
Triple - Helper class for working with autoconf configuration names.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
Context & getContext() const
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
@ MCDR_DataRegionEnd
.end_data_region
@ MCDR_DataRegion
.data_region
@ MCDR_DataRegionJT8
.data_region jt8
@ MCDR_DataRegionJT32
.data_region jt32
@ MCDR_DataRegionJT16
.data_region jt16
LLVM_ABI MCStreamer * createMachOStreamer(MCContext &Ctx, std::unique_ptr< MCAsmBackend > &&TAB, std::unique_ptr< MCObjectWriter > &&OW, std::unique_ptr< MCCodeEmitter > &&CE, bool DWARFMustBeAtTheEnd, bool LabelSections=false)
Definition MCMachOStreamer.cpp:493
MCLOHDirective::LOHArgs MCLOHArgs
FunctionAddr VTableAddr Count
FunctionAddr VTableAddr uintptr_t uintptr_t Data
MCLOHType
Linker Optimization Hint Type.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
@ MCSA_WeakDefAutoPrivate
.weak_def_can_be_hidden (MachO)
@ MCSA_Memtag
.memtag (ELF)
@ MCSA_Protected
.protected (ELF)
@ MCSA_Exported
.globl _foo, exported (XCOFF)
@ MCSA_PrivateExtern
.private_extern (MachO)
@ MCSA_Internal
.internal (ELF)
@ MCSA_WeakReference
.weak_reference (MachO)
@ MCSA_AltEntry
.alt_entry (MachO)
@ MCSA_ELF_TypeIndFunction
.type _foo, STT_GNU_IFUNC
@ MCSA_LazyReference
.lazy_reference (MachO)
@ MCSA_ELF_TypeNoType
.type _foo, STT_NOTYPE # aka @notype
@ MCSA_Reference
.reference (MachO)
@ MCSA_SymbolResolver
.symbol_resolver (MachO)
@ MCSA_ELF_TypeTLS
.type _foo, STT_TLS # aka @tls_object
@ MCSA_IndirectSymbol
.indirect_symbol (MachO)
@ MCSA_WeakDefinition
.weak_definition (MachO)
@ MCSA_ELF_TypeCommon
.type _foo, STT_COMMON # aka @common
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_WeakAntiDep
.weak_anti_dep (COFF)
@ MCSA_Extern
.extern (XCOFF)
@ MCSA_ELF_TypeObject
.type _foo, STT_OBJECT # aka @object
@ MCSA_ELF_TypeGnuUniqueObject
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
@ MCSA_LGlobal
.lglobl (XCOFF)
@ MCSA_Invalid
Not a valid directive.
@ MCSA_NoDeadStrip
.no_dead_strip (MachO)