LLVM 22.0.0git
MCWinCOFFStreamer.cpp
Go to the documentation of this file.
1//===- llvm/MC/MCWinCOFFStreamer.cpp --------------------------------------===//
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// This file contains an implementation of a Windows COFF object file streamer.
10//
11//===----------------------------------------------------------------------===//
12
16#include "llvm/ADT/Twine.h"
19#include "llvm/MC/MCAssembler.h"
21#include "llvm/MC/MCCodeView.h"
22#include "llvm/MC/MCContext.h"
23#include "llvm/MC/MCExpr.h"
24#include "llvm/MC/MCFixup.h"
31#include "llvm/MC/MCValue.h"
35#include "llvm/Support/SMLoc.h"
38#include <algorithm>
39#include <cstdint>
40
41using namespace llvm;
42
43#define DEBUG_TYPE "WinCOFFStreamer"
44
45/// MCExpr that represents the physical number for the sections that contains
46/// a symbol.
48 const MCSymbol &SectionSymbol;
49 const WinCOFFObjectWriter &Writer;
50
51 MCCOFFSectionNumberTargetExpr(const MCSymbol &SectionSymbol_,
52 const WinCOFFObjectWriter &Writer_)
53 : SectionSymbol(SectionSymbol_), Writer(Writer_) {}
54
55public:
57 create(const MCSymbol &SectionSymbol, const WinCOFFObjectWriter &Writer,
58 MCContext &Ctx) {
59 return new (Ctx) MCCOFFSectionNumberTargetExpr(SectionSymbol, Writer);
60 }
61
62 void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override {
63 OS << ":secnum:";
64 SectionSymbol.print(OS, MAI);
65 }
66
68 const MCAssembler *Asm) const override {
69 auto sectionNumber = Writer.getSectionNumber(SectionSymbol.getSection());
70 assert(sectionNumber != 0 &&
71 "Containing section was not assigned a number");
72 Res = MCValue::get(sectionNumber);
73 return true;
74 }
75
76 void visitUsedExpr(MCStreamer &Streamer) const override {
77 // Contains no sub-expressions.
78 }
79
81 return SectionSymbol.getFragment();
82 }
83};
84
85/// MCExpr that represents the offset to a symbol from the beginning of its
86/// section.
88 const MCSymbol &Symbol;
89
90 MCCOFFSectionOffsetTargetExpr(const MCSymbol &Symbol_) : Symbol(Symbol_) {}
91
92public:
94 MCContext &Ctx) {
95 return new (Ctx) MCCOFFSectionOffsetTargetExpr(Symbol);
96 }
97
98 void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override {
99 OS << ":secoffset:";
100 Symbol.print(OS, MAI);
101 }
102
104 const MCAssembler *Asm) const override {
105 uint64_t CallsiteOffset = 0;
106 if (!Asm->getSymbolOffset(Symbol, CallsiteOffset)) {
107 return true;
108 }
109 Res = MCValue::get(CallsiteOffset);
110 return true;
111 }
112
113 void visitUsedExpr(MCStreamer &Streamer) const override {
114 // Contains no sub-expressions.
115 }
116
118 return Symbol.getFragment();
119 }
120};
121
123 std::unique_ptr<MCAsmBackend> MAB,
124 std::unique_ptr<MCCodeEmitter> CE,
125 std::unique_ptr<MCObjectWriter> OW)
126 : MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)),
127 CurSymbol(nullptr) {
128 auto *TO = Context.getTargetOptions();
129 if (TO && TO->MCIncrementalLinkerCompatible)
131}
132
134 return static_cast<WinCOFFObjectWriter &>(getAssembler().getWriter());
135}
136
138 const MCSubtargetInfo &STI) {
139 // FIXME: this is identical to the ELF one.
140 // This emulates the same behavior of GNU as. This makes it easier
141 // to compare the output as the major sections are in the same order.
142 switchSection(getContext().getObjectFileInfo()->getTextSection());
143 emitCodeAlignment(Align(4), &STI);
144
145 switchSection(getContext().getObjectFileInfo()->getDataSection());
146 emitCodeAlignment(Align(4), &STI);
147
148 switchSection(getContext().getObjectFileInfo()->getBSSSection());
149 emitCodeAlignment(Align(4), &STI);
150
151 switchSection(getContext().getObjectFileInfo()->getTextSection());
152}
153
155 MCObjectStreamer::changeSection(Section, Subsection);
156 // Ensure that the first and the second symbols relative to the section are
157 // the section symbol and the COMDAT symbol.
158 getAssembler().registerSymbol(*Section->getBeginSymbol());
159 if (auto *Sym =
160 static_cast<const MCSectionCOFF *>(Section)->getCOMDATSymbol())
162}
163
165 auto *Symbol = static_cast<MCSymbolCOFF *>(S);
166 MCObjectStreamer::emitLabel(Symbol, Loc);
167}
168
171 auto *Symbol = static_cast<MCSymbolCOFF *>(S);
172 getAssembler().registerSymbol(*Symbol);
173
174 switch (Attribute) {
175 default: return false;
177 case MCSA_Weak:
178 Symbol->setWeakExternalCharacteristics(COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS);
179 Symbol->setExternal(true);
180 break;
181 case MCSA_WeakAntiDep:
182 Symbol->setWeakExternalCharacteristics(COFF::IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY);
183 Symbol->setExternal(true);
184 Symbol->setIsWeakExternal(true);
185 break;
186 case MCSA_Global:
187 Symbol->setExternal(true);
188 break;
189 case MCSA_AltEntry:
190 llvm_unreachable("COFF doesn't support the .alt_entry attribute");
191 }
192
193 return true;
194}
195
196void MCWinCOFFStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
197 llvm_unreachable("not implemented");
198}
199
201 if (CurSymbol)
202 Error("starting a new symbol definition without completing the "
203 "previous one");
204 CurSymbol = static_cast<MCSymbolCOFF *>(const_cast<MCSymbol *>(S));
205}
206
208 if (!CurSymbol) {
209 Error("storage class specified outside of symbol definition");
210 return;
211 }
212
214 Error("storage class value '" + Twine(StorageClass) +
215 "' out of range");
216 return;
217 }
218
220 static_cast<MCSymbolCOFF *>(CurSymbol)->setClass((uint16_t)StorageClass);
221}
222
224 if (!CurSymbol) {
225 Error("symbol type specified outside of a symbol definition");
226 return;
227 }
228
229 if (Type & ~0xffff) {
230 Error("type value '" + Twine(Type) + "' out of range");
231 return;
232 }
233
235 static_cast<const MCSymbolCOFF *>(CurSymbol)->setType((uint16_t)Type);
236}
237
239 if (!CurSymbol)
240 Error("ending symbol definition without starting one");
241 CurSymbol = nullptr;
242}
243
245 // SafeSEH is a feature specific to 32-bit x86. It does not exist (and is
246 // unnecessary) on all platforms which use table-based exception dispatch.
247 if (getContext().getTargetTriple().getArch() != Triple::x86)
248 return;
249
250 auto *CSymbol = static_cast<const MCSymbolCOFF *>(Symbol);
251 if (CSymbol->isSafeSEH())
252 return;
253
255 pushSection();
256 switchSection(SXData);
257 SXData->ensureMinAlignment(Align(4));
258
259 newSpecialFragment<MCSymbolIdFragment>(Symbol);
260 getAssembler().registerSymbol(*Symbol);
261 CSymbol->setIsSafeSEH();
262
263 // The Microsoft linker requires that the symbol type of a handler be
264 // function. Go ahead and oblige it here.
265 CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION
267 popSection();
268}
269
272 Sec->ensureMinAlignment(Align(4));
273
274 newSpecialFragment<MCSymbolIdFragment>(Symbol);
275 getAssembler().registerSymbol(*Symbol);
276}
277
279 visitUsedSymbol(*Symbol);
280 const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
282 addFixup(SRE, FK_SecRel_2);
283 appendContents(2, 0);
284}
285
288 visitUsedSymbol(*Symbol);
289 // Create Symbol A for the relocation relative reference.
290 const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext());
291 // Add the constant offset, if given.
292 if (Offset)
296 addFixup(MCE, FK_SecRel_4);
297 // Emit 4 bytes (zeros) to the object file.
298 appendContents(4, 0);
299}
300
302 int64_t Offset) {
303 visitUsedSymbol(*Symbol);
304 // Create Symbol A for the relocation relative reference.
305 const MCExpr *MCE = MCSymbolRefExpr::create(
307 // Add the constant offset, if given.
308 if (Offset)
312 addFixup(MCE, FK_Data_4);
313 // Emit 4 bytes (zeros) to the object file.
314 appendContents(4, 0);
315}
316
318 visitUsedSymbol(*Symbol);
319 // Create Symbol for section number.
321 *Symbol, this->getWriter(), getContext());
323 addFixup(MCE, FK_Data_4);
324 // Emit 4 bytes (zeros) to the object file.
325 appendContents(4, 0);
326}
327
329 visitUsedSymbol(*Symbol);
330 // Create Symbol for section offset.
331 const MCExpr *MCE =
334 addFixup(MCE, FK_Data_4);
335 // Emit 4 bytes (zeros) to the object file.
336 appendContents(4, 0);
337}
338
340 Align ByteAlignment) {
341 auto *Symbol = static_cast<MCSymbolCOFF *>(S);
342
343 const Triple &T = getContext().getTargetTriple();
344 if (T.isWindowsMSVCEnvironment()) {
345 if (ByteAlignment > 32)
346 report_fatal_error("alignment is limited to 32-bytes");
347
348 // Round size up to alignment so that we will honor the alignment request.
349 Size = std::max(Size, ByteAlignment.value());
350 }
351
352 getAssembler().registerSymbol(*Symbol);
353 Symbol->setExternal(true);
354 Symbol->setCommon(Size, ByteAlignment);
355
356 if (!T.isWindowsMSVCEnvironment() && ByteAlignment > 1) {
360
361 OS << " -aligncomm:\"" << Symbol->getName() << "\","
362 << Log2_32_Ceil(ByteAlignment.value());
363
364 pushSection();
367 popSection();
368 }
369}
370
372 Align ByteAlignment) {
373 auto *Symbol = static_cast<MCSymbolCOFF *>(S);
374
376 pushSection();
377 switchSection(Section);
378 emitValueToAlignment(ByteAlignment, 0, 1, 0);
379 emitLabel(Symbol);
380 Symbol->setExternal(false);
382 popSection();
383}
384
385// Hack: Used by llvm-ml to implement the alias directive.
387 const MCSymbol *Symbol) {
388 auto *Alias = static_cast<MCSymbolCOFF *>(AliasS);
390 Alias->setIsWeakExternal(true);
391
392 getAssembler().registerSymbol(*Symbol);
393 Alias->setVariableValue(MCSymbolRefExpr::create(Symbol, getContext()));
394}
395
396// TODO: Implement this if you want to emit .comment section in COFF obj files.
398 llvm_unreachable("not implemented");
399}
400
402 llvm_unreachable("not implemented");
403}
404
406 const MCSymbolRefExpr *To,
407 uint64_t Count) {
408 // Ignore temporary symbols for now.
409 if (!From->getSymbol().isTemporary() && !To->getSymbol().isTemporary())
410 getWriter().getCGProfile().push_back({From, To, Count});
411}
412
414 const MCSymbol *S = &SRE->getSymbol();
415 if (getAssembler().registerSymbol(*S))
416 static_cast<const MCSymbolCOFF *>(S)->setExternal(true);
417}
418
421 MCAssembler &Asm = getAssembler();
422 if (Asm.getWriter().getEmitAddrsigSection()) {
423 // Register the section.
424 switchSection(Asm.getContext().getCOFFSection(".llvm_addrsig",
426 }
427 if (!Asm.getWriter().getCGProfile().empty()) {
428 for (auto &E : Asm.getWriter().getCGProfile()) {
431 }
432 switchSection(Asm.getContext().getCOFFSection(".llvm.call-graph-profile",
434 }
435
437}
438
439void MCWinCOFFStreamer::Error(const Twine &Msg) const {
440 getContext().reportError(SMLoc(), Msg);
441}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
BlockVerifier::State From
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:479
raw_pwrite_stream & OS
This file defines the SmallString class.
This file defines the SmallVector class.
MCExpr that represents the physical number for the sections that contains a symbol.
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override
static MCCOFFSectionNumberTargetExpr * create(const MCSymbol &SectionSymbol, const WinCOFFObjectWriter &Writer, MCContext &Ctx)
void visitUsedExpr(MCStreamer &Streamer) const override
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm) const override
MCFragment * findAssociatedFragment() const override
MCExpr that represents the offset to a symbol from the beginning of its section.
MCFragment * findAssociatedFragment() const override
static MCCOFFSectionOffsetTargetExpr * create(const MCSymbol &Symbol, MCContext &Ctx)
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm) const override
void visitUsedExpr(MCStreamer &Streamer) const override
Lightweight error class with error context and mandatory checking.
Definition: Error.h:159
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:64
MCObjectWriter & getWriter() const
Definition: MCAssembler.h:179
LLVM_ABI bool registerSymbol(const MCSymbol &Symbol)
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:343
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:212
Context object for machine code objects.
Definition: MCContext.h:83
const MCObjectFileInfo * getObjectFileInfo() const
Definition: MCContext.h:416
LLVM_ABI CodeViewContext & getCVContext()
Definition: MCContext.cpp:1060
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1115
const Triple & getTargetTriple() const
Definition: MCContext.h:400
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
MCSection * getSXDataSection() const
MCSection * getBSSSection() const
MCSection * getDrectveSection() const
Streaming object file generation interface.
void emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0) override
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
MCAssembler & getAssembler()
void appendContents(ArrayRef< char > Contents)
void emitBytes(StringRef Data) override
Emit the bytes in Data into the output.
void addFixup(const MCExpr *Value, MCFixupKind Kind)
void visitUsedSymbol(const MCSymbol &Sym) override
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.
void emitCodeAlignment(Align ByteAlignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit=0) override
Emit nops until the byte alignment ByteAlignment is reached.
void ensureHeadroom(size_t Headroom)
SmallVector< CGProfileEntry, 0 > & getCGProfile()
This represents a section on Windows.
Definition: MCSectionCOFF.h:27
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:496
void ensureMinAlignment(Align MinAlignment)
Makes sure that Alignment is at least MinAlignment.
Definition: MCSection.h:583
Streaming machine code generation interface.
Definition: MCStreamer.h:220
virtual bool popSection()
Restore the current and previous section from the section stack.
MCContext & getContext() const
Definition: MCStreamer.h:314
void pushSection()
Save the current and previous section on the section stack.
Definition: MCStreamer.h:443
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
MCSection * getCurrentSectionOnly() const
Definition: MCStreamer.h:421
void emitZeros(uint64_t NumBytes)
Emit NumBytes worth of zeros.
Definition: MCStreamer.cpp:204
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:190
const MCSymbol & getSymbol() const
Definition: MCExpr.h:227
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
Definition: MCSymbol.h:205
Extension point for target-specific MCExpr subclasses to implement.
Definition: MCExpr.h:465
static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB=nullptr, int64_t Val=0, uint32_t Specifier=0)
Definition: MCValue.h:56
void emitCOFFSectionIndex(MCSymbol const *Symbol) override
Emits a COFF section index.
void finalizeCGProfileEntry(const MCSymbolRefExpr *&S)
void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override
Emits a COFF image relative relocation.
void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc()) override
Emit a label for Symbol into the current section.
void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override
Emit an weak reference from Alias to Symbol.
void initSections(bool NoExecStack, const MCSubtargetInfo &STI) override
Create the default sections and set the initial one.
void emitCOFFSafeSEH(MCSymbol const *Symbol) override
void emitCOFFSecOffset(MCSymbol const *Symbol) override
Emits the offset of the symbol from the beginning of the section during object writing (i....
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment) override
Emit a common symbol.
void endCOFFSymbolDef() override
Marks the end of the symbol definition.
MCWinCOFFStreamer(MCContext &Context, std::unique_ptr< MCAsmBackend > MAB, std::unique_ptr< MCCodeEmitter > CE, std::unique_ptr< MCObjectWriter > OW)
void changeSection(MCSection *Section, uint32_t Subsection=0) override
This is called by popSection and switchSection, if the current section changes.
void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override
Emits a COFF section relative relocation.
void finishImpl() override
Streamer specific finalization.
void emitIdent(StringRef IdentString) override
Emit the "identifiers" directive.
void emitCGProfileEntry(const MCSymbolRefExpr *From, const MCSymbolRefExpr *To, uint64_t Count) override
void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment) override
Emit a local common (.lcomm) symbol.
WinCOFFObjectWriter & getWriter()
void emitCOFFSymbolType(int Type) override
Emit the type of the symbol.
void emitCOFFSecNumber(MCSymbol const *Symbol) override
Emits the physical number of the section containing the given symbol as assigned during object writin...
void emitWinEHHandlerData(SMLoc Loc) override
void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override
Set the DescValue for the Symbol.
bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override
Add the given Attribute to Symbol.
void emitCOFFSymbolIndex(MCSymbol const *Symbol) override
Emits the symbol table index of a Symbol into the current section.
void beginCOFFSymbolDef(MCSymbol const *Symbol) override
Start emitting COFF symbol definition.
void emitCOFFSymbolStorageClass(int StorageClass) override
Emit the storage class of the symbol.
Represents a location in source code.
Definition: SMLoc.h:23
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:47
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
int getSectionNumber(const MCSection &Section) const
void setIncrementalLinkerCompatible(bool Value)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:692
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ IMAGE_SCN_LNK_REMOVE
Definition: COFF.h:308
@ SSC_Invalid
Definition: COFF.h:219
@ IMAGE_WEAK_EXTERN_SEARCH_ALIAS
Definition: COFF.h:490
@ IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY
Definition: COFF.h:491
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
Definition: COFF.h:276
@ SCT_COMPLEX_TYPE_SHIFT
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
Definition: COFF.h:280
StorageClass
Definition: XCOFF.h:171
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
Definition: MathExtras.h:349
@ Offset
Definition: DWP.cpp:477
@ FK_SecRel_2
A two-byte section relative fixup.
Definition: MCFixup.h:40
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:36
@ FK_SecRel_4
A four-byte section relative fixup.
Definition: MCFixup.h:41
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1886
MCSymbolAttr
Definition: MCDirectives.h:18
@ MCSA_WeakReference
.weak_reference (MachO)
Definition: MCDirectives.h:47
@ MCSA_AltEntry
.alt_entry (MachO)
Definition: MCDirectives.h:41
@ MCSA_Weak
.weak
Definition: MCDirectives.h:45
@ MCSA_Global
.type _foo, @gnu_unique_object
Definition: MCDirectives.h:30
@ MCSA_WeakAntiDep
.weak_anti_dep (COFF)
Definition: MCDirectives.h:49
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39