LLVM 17.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/MCContext.h"
22#include "llvm/MC/MCExpr.h"
23#include "llvm/MC/MCFixup.h"
24#include "llvm/MC/MCFragment.h"
28#include "llvm/MC/MCSection.h"
33#include "llvm/Support/SMLoc.h"
36#include <algorithm>
37#include <cstdint>
38
39using namespace llvm;
40
41#define DEBUG_TYPE "WinCOFFStreamer"
42
44 std::unique_ptr<MCAsmBackend> MAB,
45 std::unique_ptr<MCCodeEmitter> CE,
46 std::unique_ptr<MCObjectWriter> OW)
47 : MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)),
48 CurSymbol(nullptr) {}
49
51 const MCSubtargetInfo &STI) {
53
56 raw_svector_ostream VecOS(Code);
57 getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
58
59 // Add the fixups and data.
60 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
61 Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
62 DF->getFixups().push_back(Fixups[i]);
63 }
64 DF->setHasInstructions(STI);
65 DF->getContents().append(Code.begin(), Code.end());
66}
67
68void MCWinCOFFStreamer::initSections(bool NoExecStack,
69 const MCSubtargetInfo &STI) {
70 // FIXME: this is identical to the ELF one.
71 // This emulates the same behavior of GNU as. This makes it easier
72 // to compare the output as the major sections are in the same order.
73 switchSection(getContext().getObjectFileInfo()->getTextSection());
74 emitCodeAlignment(Align(4), &STI);
75
76 switchSection(getContext().getObjectFileInfo()->getDataSection());
77 emitCodeAlignment(Align(4), &STI);
78
79 switchSection(getContext().getObjectFileInfo()->getBSSSection());
80 emitCodeAlignment(Align(4), &STI);
81
82 switchSection(getContext().getObjectFileInfo()->getTextSection());
83}
84
86 auto *Symbol = cast<MCSymbolCOFF>(S);
87 MCObjectStreamer::emitLabel(Symbol, Loc);
88}
89
91 // Let the target do whatever target specific stuff it needs to do.
93
94 switch (Flag) {
95 // None of these require COFF specific handling.
97 case MCAF_Code16:
98 case MCAF_Code32:
99 case MCAF_Code64:
100 break;
102 llvm_unreachable("COFF doesn't support .subsections_via_symbols");
103 }
104}
105
107 llvm_unreachable("not implemented");
108}
109
112 auto *Symbol = cast<MCSymbolCOFF>(S);
113 getAssembler().registerSymbol(*Symbol);
114
115 switch (Attribute) {
116 default: return false;
118 case MCSA_Weak:
119 Symbol->setIsWeakExternal();
120 Symbol->setExternal(true);
121 break;
122 case MCSA_Global:
123 Symbol->setExternal(true);
124 break;
125 case MCSA_AltEntry:
126 llvm_unreachable("COFF doesn't support the .alt_entry attribute");
127 }
128
129 return true;
130}
131
132void MCWinCOFFStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
133 llvm_unreachable("not implemented");
134}
135
137 auto *Symbol = cast<MCSymbolCOFF>(S);
138 if (CurSymbol)
139 Error("starting a new symbol definition without completing the "
140 "previous one");
141 CurSymbol = Symbol;
142}
143
145 if (!CurSymbol) {
146 Error("storage class specified outside of symbol definition");
147 return;
148 }
149
151 Error("storage class value '" + Twine(StorageClass) +
152 "' out of range");
153 return;
154 }
155
157 cast<MCSymbolCOFF>(CurSymbol)->setClass((uint16_t)StorageClass);
158}
159
161 if (!CurSymbol) {
162 Error("symbol type specified outside of a symbol definition");
163 return;
164 }
165
166 if (Type & ~0xffff) {
167 Error("type value '" + Twine(Type) + "' out of range");
168 return;
169 }
170
172 cast<MCSymbolCOFF>(CurSymbol)->setType((uint16_t)Type);
173}
174
176 if (!CurSymbol)
177 Error("ending symbol definition without starting one");
178 CurSymbol = nullptr;
179}
180
182 // SafeSEH is a feature specific to 32-bit x86. It does not exist (and is
183 // unnecessary) on all platforms which use table-based exception dispatch.
184 if (getContext().getTargetTriple().getArch() != Triple::x86)
185 return;
186
187 const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol);
188 if (CSymbol->isSafeSEH())
189 return;
190
192 getAssembler().registerSection(*SXData);
193 SXData->ensureMinAlignment(Align(4));
194
195 new MCSymbolIdFragment(Symbol, SXData);
196
197 getAssembler().registerSymbol(*Symbol);
198 CSymbol->setIsSafeSEH();
199
200 // The Microsoft linker requires that the symbol type of a handler be
201 // function. Go ahead and oblige it here.
204}
205
209 Sec->ensureMinAlignment(Align(4));
210
212
213 getAssembler().registerSymbol(*Symbol);
214}
215
217 visitUsedSymbol(*Symbol);
219 const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
220 MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2);
221 DF->getFixups().push_back(Fixup);
222 DF->getContents().resize(DF->getContents().size() + 2, 0);
223}
224
227 visitUsedSymbol(*Symbol);
229 // Create Symbol A for the relocation relative reference.
230 const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext());
231 // Add the constant offset, if given.
232 if (Offset)
235 // Build the secrel32 relocation.
236 MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4);
237 // Record the relocation.
238 DF->getFixups().push_back(Fixup);
239 // Emit 4 bytes (zeros) to the object file.
240 DF->getContents().resize(DF->getContents().size() + 4, 0);
241}
242
244 int64_t Offset) {
245 visitUsedSymbol(*Symbol);
247 // Create Symbol A for the relocation relative reference.
248 const MCExpr *MCE = MCSymbolRefExpr::create(
250 // Add the constant offset, if given.
251 if (Offset)
254 // Build the imgrel relocation.
255 MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
256 // Record the relocation.
257 DF->getFixups().push_back(Fixup);
258 // Emit 4 bytes (zeros) to the object file.
259 DF->getContents().resize(DF->getContents().size() + 4, 0);
260}
261
263 Align ByteAlignment) {
264 auto *Symbol = cast<MCSymbolCOFF>(S);
265
266 const Triple &T = getContext().getTargetTriple();
267 if (T.isWindowsMSVCEnvironment()) {
268 if (ByteAlignment > 32)
269 report_fatal_error("alignment is limited to 32-bytes");
270
271 // Round size up to alignment so that we will honor the alignment request.
272 Size = std::max(Size, ByteAlignment.value());
273 }
274
275 getAssembler().registerSymbol(*Symbol);
276 Symbol->setExternal(true);
277 Symbol->setCommon(Size, ByteAlignment);
278
279 if (!T.isWindowsMSVCEnvironment() && ByteAlignment > 1) {
283
284 OS << " -aligncomm:\"" << Symbol->getName() << "\","
285 << Log2_32_Ceil(ByteAlignment.value());
286
287 pushSection();
290 popSection();
291 }
292}
293
295 Align ByteAlignment) {
296 auto *Symbol = cast<MCSymbolCOFF>(S);
297
299 pushSection();
300 switchSection(Section);
301 emitValueToAlignment(ByteAlignment, 0, 1, 0);
302 emitLabel(Symbol);
303 Symbol->setExternal(false);
305 popSection();
306}
307
309 const MCSymbol *Symbol) {
310 auto *Alias = cast<MCSymbolCOFF>(AliasS);
312
313 getAssembler().registerSymbol(*Symbol);
314 Alias->setVariableValue(MCSymbolRefExpr::create(
316}
317
319 uint64_t Size, Align ByteAlignment,
320 SMLoc Loc) {
321 llvm_unreachable("not implemented");
322}
323
325 uint64_t Size, Align ByteAlignment) {
326 llvm_unreachable("not implemented");
327}
328
329// TODO: Implement this if you want to emit .comment section in COFF obj files.
331 llvm_unreachable("not implemented");
332}
333
335 llvm_unreachable("not implemented");
336}
337
339 const MCSymbolRefExpr *To,
340 uint64_t Count) {
341 // Ignore temporary symbols for now.
342 if (!From->getSymbol().isTemporary() && !To->getSymbol().isTemporary())
343 getAssembler().CGProfile.push_back({From, To, Count});
344}
345
347 const MCSymbol *S = &SRE->getSymbol();
348 bool Created;
349 getAssembler().registerSymbol(*S, &Created);
350 if (Created)
351 cast<MCSymbolCOFF>(S)->setExternal(true);
352}
353
355 for (MCAssembler::CGProfileEntry &E : getAssembler().CGProfile) {
358 }
359}
360
363
365}
366
367void MCWinCOFFStreamer::Error(const Twine &Msg) const {
368 getContext().reportError(SMLoc(), Msg);
369}
BlockVerifier::State From
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
uint64_t Size
LLVMContext & Context
PowerPC TLS Dynamic Call Fixup
raw_pwrite_stream & OS
This file defines the SmallString class.
This file defines the SmallVector class.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
virtual void handleAssemblerFlag(MCAssemblerFlag Flag)
Handle any target-specific assembler flags. By default, do nothing.
Definition: MCAsmBackend.h:210
void registerSymbol(const MCSymbol &Symbol, bool *Created=nullptr)
MCCodeEmitter & getEmitter() const
Definition: MCAssembler.h:331
MCAsmBackend & getBackend() const
Definition: MCAssembler.h:329
std::vector< CGProfileEntry > CGProfile
Definition: MCAssembler.h:470
bool registerSection(MCSection &Section)
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:525
virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
EncodeInstruction - Encode the given Inst to bytes on the output stream OS.
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:76
const MCObjectFileInfo * getObjectFileInfo() const
Definition: MCContext.h:450
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1052
const Triple & getTargetTriple() const
Definition: MCContext.h:434
Fragment for data and encoded instructions.
Definition: MCFragment.h:241
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
MCSection * getSXDataSection() const
MCSection * getBSSSection() const
MCSection * getDrectveSection() const
Streaming object file generation interface.
void emitValueToAlignment(Align Alignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0) override
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
MCDataFragment * getOrCreateDataFragment(const MCSubtargetInfo *STI=nullptr)
Get a data fragment to write into, creating a new one if the current fragment is not a data fragment.
MCAssembler & getAssembler()
void emitBytes(StringRef Data) override
Emit the bytes in Data into the output.
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 emitCodeAlignment(Align ByteAlignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit=0) override
Emit nops until the byte alignment ByteAlignment is reached.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:39
void ensureMinAlignment(Align MinAlignment)
Makes sure that Alignment is at least MinAlignment.
Definition: MCSection.h:144
MCContext & getContext() const
Definition: MCStreamer.h:297
bool popSection()
Restore the current and previous section from the section stack.
Definition: MCStreamer.h:424
void pushSection()
Save the current and previous section on the section stack.
Definition: MCStreamer.h:415
virtual void switchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
MCSection * getCurrentSectionOnly() const
Definition: MCStreamer.h:393
void emitZeros(uint64_t NumBytes)
Emit NumBytes worth of zeros.
Definition: MCStreamer.cpp:229
Generic base class for all target subtargets.
void setIsSafeSEH() const
Definition: MCSymbolCOFF.h:57
void setType(uint16_t Ty) const
Definition: MCSymbolCOFF.h:36
bool isSafeSEH() const
Definition: MCSymbolCOFF.h:54
Represents a symbol table index fragment.
Definition: MCFragment.h:498
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
const MCSymbol & getSymbol() const
Definition: MCExpr.h:399
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:386
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
Definition: MCSymbol.h:220
void emitCOFFSectionIndex(MCSymbol const *Symbol) override
Emits a COFF section index.
void emitAssemblerFlag(MCAssemblerFlag Flag) override
Note in the output the specified Flag.
void finalizeCGProfileEntry(const MCSymbolRefExpr *&S)
void emitThumbFunc(MCSymbol *Func) override
Note in the output that the specified Func is a Thumb mode function (ARM target only).
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 emitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, Align ByteAlignment, SMLoc Loc=SMLoc()) override
Emit the zerofill section and an optional symbol.
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 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 emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, Align ByteAlignment) override
Emit a thread local bss (.tbss) symbol.
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.
void emitCOFFSymbolType(int Type) override
Emit the type of the symbol.
void emitWinEHHandlerData(SMLoc Loc) override
void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override
Set the DescValue for the Symbol.
const MCSymbol * CurSymbol
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 emitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override
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
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:672
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SSC_Invalid
Definition: COFF.h:204
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
Definition: COFF.h:261
@ SCT_COMPLEX_TYPE_SHIFT
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
Definition: COFF.h:265
StorageClass
Definition: XCOFF.h:169
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:395
@ Offset
Definition: DWP.cpp:406
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
@ FK_SecRel_2
A two-byte section relative fixup.
Definition: MCFixup.h:41
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:25
@ FK_SecRel_4
A four-byte section relative fixup.
Definition: MCFixup.h:42
MCAssemblerFlag
Definition: MCDirectives.h:52
@ MCAF_SyntaxUnified
.syntax (ARM/ELF)
Definition: MCDirectives.h:53
@ MCAF_Code64
.code64 (X86)
Definition: MCDirectives.h:57
@ MCAF_Code16
.code16 (X86) / .code 16 (ARM)
Definition: MCDirectives.h:55
@ MCAF_Code32
.code32 (X86) / .code 32 (ARM)
Definition: MCDirectives.h:56
@ MCAF_SubsectionsViaSymbols
.subsections_via_symbols (MachO)
Definition: MCDirectives.h:54
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:1946
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
Definition: BitVector.h:858
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39