xref: /freebsd/contrib/llvm-project/llvm/lib/MC/XCOFFObjectWriter.cpp (revision 8bcb0991864975618c09697b1aca10683346d9f0)
1 //===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===//
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 implements XCOFF object file writer information.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/BinaryFormat/XCOFF.h"
14 #include "llvm/MC/MCAsmLayout.h"
15 #include "llvm/MC/MCAssembler.h"
16 #include "llvm/MC/MCObjectWriter.h"
17 #include "llvm/MC/MCSectionXCOFF.h"
18 #include "llvm/MC/MCSymbolXCOFF.h"
19 #include "llvm/MC/MCValue.h"
20 #include "llvm/MC/MCXCOFFObjectWriter.h"
21 #include "llvm/MC/StringTableBuilder.h"
22 #include "llvm/Support/Error.h"
23 #include "llvm/Support/MathExtras.h"
24 
25 #include <deque>
26 
27 using namespace llvm;
28 
29 // An XCOFF object file has a limited set of predefined sections. The most
30 // important ones for us (right now) are:
31 // .text --> contains program code and read-only data.
32 // .data --> contains initialized data, function descriptors, and the TOC.
33 // .bss  --> contains uninitialized data.
34 // Each of these sections is composed of 'Control Sections'. A Control Section
35 // is more commonly referred to as a csect. A csect is an indivisible unit of
36 // code or data, and acts as a container for symbols. A csect is mapped
37 // into a section based on its storage-mapping class, with the exception of
38 // XMC_RW which gets mapped to either .data or .bss based on whether it's
39 // explicitly initialized or not.
40 //
41 // We don't represent the sections in the MC layer as there is nothing
42 // interesting about them at at that level: they carry information that is
43 // only relevant to the ObjectWriter, so we materialize them in this class.
44 namespace {
45 
46 constexpr unsigned DefaultSectionAlign = 4;
47 
48 // Packs the csect's alignment and type into a byte.
49 uint8_t getEncodedType(const MCSectionXCOFF *);
50 
51 // Wrapper around an MCSymbolXCOFF.
52 struct Symbol {
53   const MCSymbolXCOFF *const MCSym;
54   uint32_t SymbolTableIndex;
55 
56   XCOFF::StorageClass getStorageClass() const {
57     return MCSym->getStorageClass();
58   }
59   StringRef getName() const { return MCSym->getName(); }
60   Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
61 };
62 
63 // Wrapper for an MCSectionXCOFF.
64 struct ControlSection {
65   const MCSectionXCOFF *const MCCsect;
66   uint32_t SymbolTableIndex;
67   uint32_t Address;
68   uint32_t Size;
69 
70   SmallVector<Symbol, 1> Syms;
71   StringRef getName() const { return MCCsect->getSectionName(); }
72   ControlSection(const MCSectionXCOFF *MCSec)
73       : MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
74 };
75 
76 // Represents the data related to a section excluding the csects that make up
77 // the raw data of the section. The csects are stored separately as not all
78 // sections contain csects, and some sections contain csects which are better
79 // stored separately, e.g. the .data section containing read-write, descriptor,
80 // TOCBase and TOC-entry csects.
81 struct Section {
82   char Name[XCOFF::NameSize];
83   // The physical/virtual address of the section. For an object file
84   // these values are equivalent.
85   uint32_t Address;
86   uint32_t Size;
87   uint32_t FileOffsetToData;
88   uint32_t FileOffsetToRelocations;
89   uint32_t RelocationCount;
90   int32_t Flags;
91 
92   int16_t Index;
93 
94   // Virtual sections do not need storage allocated in the object file.
95   const bool IsVirtual;
96 
97   void reset() {
98     Address = 0;
99     Size = 0;
100     FileOffsetToData = 0;
101     FileOffsetToRelocations = 0;
102     RelocationCount = 0;
103     Index = -1;
104   }
105 
106   Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual)
107       : Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0),
108         RelocationCount(0), Flags(Flags), Index(-1), IsVirtual(IsVirtual) {
109     strncpy(Name, N, XCOFF::NameSize);
110   }
111 };
112 
113 class XCOFFObjectWriter : public MCObjectWriter {
114   // Type to be used for a container representing a set of csects with
115   // (approximately) the same storage mapping class. For example all the csects
116   // with a storage mapping class of `xmc_pr` will get placed into the same
117   // container.
118   using CsectGroup = std::deque<ControlSection>;
119 
120   support::endian::Writer W;
121   std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
122   StringTableBuilder Strings;
123 
124   // The non-empty sections, in the order they will appear in the section header
125   // table.
126   std::vector<Section *> Sections;
127 
128   // The Predefined sections.
129   Section Text;
130   Section BSS;
131 
132   // CsectGroups. These store the csects which make up different parts of
133   // the sections. Should have one for each set of csects that get mapped into
134   // the same section and get handled in a 'similar' way.
135   CsectGroup ProgramCodeCsects;
136   CsectGroup BSSCsects;
137 
138   uint32_t SymbolTableEntryCount = 0;
139   uint32_t SymbolTableOffset = 0;
140 
141   virtual void reset() override;
142 
143   void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
144 
145   void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
146                         const MCFixup &, MCValue, uint64_t &) override;
147 
148   uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
149 
150   static bool nameShouldBeInStringTable(const StringRef &);
151   void writeSymbolName(const StringRef &);
152   void writeSymbolTableEntryForCsectMemberLabel(const Symbol &,
153                                                 const ControlSection &, int16_t,
154                                                 uint64_t);
155   void writeSymbolTableEntryForControlSection(const ControlSection &, int16_t,
156                                               XCOFF::StorageClass);
157   void writeFileHeader();
158   void writeSectionHeaderTable();
159   void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
160   void writeSymbolTable(const MCAsmLayout &Layout);
161 
162   // Called after all the csects and symbols have been processed by
163   // `executePostLayoutBinding`, this function handles building up the majority
164   // of the structures in the object file representation. Namely:
165   // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
166   //    sizes.
167   // *) Assigns symbol table indices.
168   // *) Builds up the section header table by adding any non-empty sections to
169   //    `Sections`.
170   void assignAddressesAndIndices(const MCAsmLayout &);
171 
172   bool
173   needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
174     return false;
175   }
176 
177   // Returns the size of the auxiliary header to be written to the object file.
178   size_t auxiliaryHeaderSize() const {
179     assert(!needsAuxiliaryHeader() &&
180            "Auxiliary header support not implemented.");
181     return 0;
182   }
183 
184 public:
185   XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
186                     raw_pwrite_stream &OS);
187 };
188 
189 XCOFFObjectWriter::XCOFFObjectWriter(
190     std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
191     : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
192       Strings(StringTableBuilder::XCOFF),
193       Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false),
194       BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true) {}
195 
196 void XCOFFObjectWriter::reset() {
197   // Reset any sections we have written to, and empty the section header table.
198   for (auto *Sec : Sections)
199     Sec->reset();
200   Sections.clear();
201 
202   // Clear any csects we have stored.
203   ProgramCodeCsects.clear();
204   BSSCsects.clear();
205 
206   // Reset the symbol table and string table.
207   SymbolTableEntryCount = 0;
208   SymbolTableOffset = 0;
209   Strings.clear();
210 
211   MCObjectWriter::reset();
212 }
213 
214 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
215                                                  const MCAsmLayout &Layout) {
216   if (TargetObjectWriter->is64Bit())
217     report_fatal_error("64-bit XCOFF object files are not supported yet.");
218 
219   // Maps the MC Section representation to its corresponding ControlSection
220   // wrapper. Needed for finding the ControlSection to insert an MCSymbol into
221   // from its containing MCSectionXCOFF.
222   DenseMap<const MCSectionXCOFF *, ControlSection *> WrapperMap;
223 
224   for (const auto &S : Asm) {
225     const auto *MCSec = cast<const MCSectionXCOFF>(&S);
226     assert(WrapperMap.find(MCSec) == WrapperMap.end() &&
227            "Cannot add a csect twice.");
228 
229     // If the name does not fit in the storage provided in the symbol table
230     // entry, add it to the string table.
231     if (nameShouldBeInStringTable(MCSec->getSectionName()))
232       Strings.add(MCSec->getSectionName());
233 
234     switch (MCSec->getMappingClass()) {
235     case XCOFF::XMC_PR:
236       assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
237              "Only an initialized csect can contain program code.");
238       ProgramCodeCsects.emplace_back(MCSec);
239       WrapperMap[MCSec] = &ProgramCodeCsects.back();
240       break;
241     case XCOFF::XMC_RW:
242       if (XCOFF::XTY_CM == MCSec->getCSectType()) {
243         BSSCsects.emplace_back(MCSec);
244         WrapperMap[MCSec] = &BSSCsects.back();
245         break;
246       }
247       report_fatal_error("Unhandled mapping of read-write csect to section.");
248     case XCOFF::XMC_TC0:
249       // TODO FIXME Handle emiting the TOC base.
250       break;
251     case XCOFF::XMC_BS:
252       assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
253              "Mapping invalid csect. CSECT with bss storage class must be "
254              "common type.");
255       BSSCsects.emplace_back(MCSec);
256       WrapperMap[MCSec] = &BSSCsects.back();
257       break;
258     default:
259       report_fatal_error("Unhandled mapping of csect to section.");
260     }
261   }
262 
263   for (const MCSymbol &S : Asm.symbols()) {
264     // Nothing to do for temporary symbols.
265     if (S.isTemporary())
266       continue;
267     const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
268 
269     // Map the symbol into its containing csect.
270     const MCSectionXCOFF *ContainingCsect = XSym->getContainingCsect();
271     assert(WrapperMap.find(ContainingCsect) != WrapperMap.end() &&
272            "Expected containing csect to exist in map");
273 
274     // Lookup the containing csect and add the symbol to it.
275     WrapperMap[ContainingCsect]->Syms.emplace_back(XSym);
276 
277     // If the name does not fit in the storage provided in the symbol table
278     // entry, add it to the string table.
279     if (nameShouldBeInStringTable(XSym->getName()))
280       Strings.add(XSym->getName());
281     }
282 
283   Strings.finalize();
284   assignAddressesAndIndices(Layout);
285 }
286 
287 void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &,
288                                          const MCFragment *, const MCFixup &,
289                                          MCValue, uint64_t &) {
290   report_fatal_error("XCOFF relocations not supported.");
291 }
292 
293 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
294                                       const MCAsmLayout &Layout) {
295   // Write the program code control sections one at a time.
296   uint32_t CurrentAddressLocation = Text.Address;
297   for (const auto &Csect : ProgramCodeCsects) {
298     if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
299       W.OS.write_zeros(PaddingSize);
300     Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
301     CurrentAddressLocation = Csect.Address + Csect.Size;
302   }
303 
304   if (Text.Index != -1) {
305     // The size of the tail padding in a section is the end virtual address of
306     // the current section minus the the end virtual address of the last csect
307     // in that section.
308     if (uint32_t PaddingSize =
309             Text.Address + Text.Size - CurrentAddressLocation)
310       W.OS.write_zeros(PaddingSize);
311   }
312 }
313 
314 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
315                                         const MCAsmLayout &Layout) {
316   // We always emit a timestamp of 0 for reproducibility, so ensure incremental
317   // linking is not enabled, in case, like with Windows COFF, such a timestamp
318   // is incompatible with incremental linking of XCOFF.
319   if (Asm.isIncrementalLinkerCompatible())
320     report_fatal_error("Incremental linking not supported for XCOFF.");
321 
322   if (TargetObjectWriter->is64Bit())
323     report_fatal_error("64-bit XCOFF object files are not supported yet.");
324 
325   uint64_t StartOffset = W.OS.tell();
326 
327   writeFileHeader();
328   writeSectionHeaderTable();
329   writeSections(Asm, Layout);
330   // TODO writeRelocations();
331 
332   writeSymbolTable(Layout);
333   // Write the string table.
334   Strings.write(W.OS);
335 
336   return W.OS.tell() - StartOffset;
337 }
338 
339 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
340   return SymbolName.size() > XCOFF::NameSize;
341 }
342 
343 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
344   if (nameShouldBeInStringTable(SymbolName)) {
345     W.write<int32_t>(0);
346     W.write<uint32_t>(Strings.getOffset(SymbolName));
347   } else {
348     char Name[XCOFF::NameSize];
349     std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
350     ArrayRef<char> NameRef(Name, XCOFF::NameSize);
351     W.write(NameRef);
352   }
353 }
354 
355 void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
356     const Symbol &SymbolRef, const ControlSection &CSectionRef,
357     int16_t SectionIndex, uint64_t SymbolOffset) {
358   // Name or Zeros and string table offset
359   writeSymbolName(SymbolRef.getName());
360   assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
361          "Symbol address overflows.");
362   W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
363   W.write<int16_t>(SectionIndex);
364   // Basic/Derived type. See the description of the n_type field for symbol
365   // table entries for a detailed description. Since we don't yet support
366   // visibility, and all other bits are either optionally set or reserved, this
367   // is always zero.
368   // TODO FIXME How to assert a symbol's visibilty is default?
369   // TODO Set the function indicator (bit 10, 0x0020) for functions
370   // when debugging is enabled.
371   W.write<uint16_t>(0);
372   W.write<uint8_t>(SymbolRef.getStorageClass());
373   // Always 1 aux entry for now.
374   W.write<uint8_t>(1);
375 
376   // Now output the auxiliary entry.
377   W.write<uint32_t>(CSectionRef.SymbolTableIndex);
378   // Parameter typecheck hash. Not supported.
379   W.write<uint32_t>(0);
380   // Typecheck section number. Not supported.
381   W.write<uint16_t>(0);
382   // Symbol type: Label
383   W.write<uint8_t>(XCOFF::XTY_LD);
384   // Storage mapping class.
385   W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
386   // Reserved (x_stab).
387   W.write<uint32_t>(0);
388   // Reserved (x_snstab).
389   W.write<uint16_t>(0);
390 }
391 
392 void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
393     const ControlSection &CSectionRef, int16_t SectionIndex,
394     XCOFF::StorageClass StorageClass) {
395   // n_name, n_zeros, n_offset
396   writeSymbolName(CSectionRef.getName());
397   // n_value
398   W.write<uint32_t>(CSectionRef.Address);
399   // n_scnum
400   W.write<int16_t>(SectionIndex);
401   // Basic/Derived type. See the description of the n_type field for symbol
402   // table entries for a detailed description. Since we don't yet support
403   // visibility, and all other bits are either optionally set or reserved, this
404   // is always zero.
405   // TODO FIXME How to assert a symbol's visibilty is default?
406   // TODO Set the function indicator (bit 10, 0x0020) for functions
407   // when debugging is enabled.
408   W.write<uint16_t>(0);
409   // n_sclass
410   W.write<uint8_t>(StorageClass);
411   // Always 1 aux entry for now.
412   W.write<uint8_t>(1);
413 
414   // Now output the auxiliary entry.
415   W.write<uint32_t>(CSectionRef.Size);
416   // Parameter typecheck hash. Not supported.
417   W.write<uint32_t>(0);
418   // Typecheck section number. Not supported.
419   W.write<uint16_t>(0);
420   // Symbol type.
421   W.write<uint8_t>(getEncodedType(CSectionRef.MCCsect));
422   // Storage mapping class.
423   W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
424   // Reserved (x_stab).
425   W.write<uint32_t>(0);
426   // Reserved (x_snstab).
427   W.write<uint16_t>(0);
428 }
429 
430 void XCOFFObjectWriter::writeFileHeader() {
431   // Magic.
432   W.write<uint16_t>(0x01df);
433   // Number of sections.
434   W.write<uint16_t>(Sections.size());
435   // Timestamp field. For reproducible output we write a 0, which represents no
436   // timestamp.
437   W.write<int32_t>(0);
438   // Byte Offset to the start of the symbol table.
439   W.write<uint32_t>(SymbolTableOffset);
440   // Number of entries in the symbol table.
441   W.write<int32_t>(SymbolTableEntryCount);
442   // Size of the optional header.
443   W.write<uint16_t>(0);
444   // Flags.
445   W.write<uint16_t>(0);
446 }
447 
448 void XCOFFObjectWriter::writeSectionHeaderTable() {
449   for (const auto *Sec : Sections) {
450     // Write Name.
451     ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
452     W.write(NameRef);
453 
454     // Write the Physical Address and Virtual Address. In an object file these
455     // are the same.
456     W.write<uint32_t>(Sec->Address);
457     W.write<uint32_t>(Sec->Address);
458 
459     W.write<uint32_t>(Sec->Size);
460     W.write<uint32_t>(Sec->FileOffsetToData);
461 
462     // Relocation pointer and Lineno pointer. Not supported yet.
463     W.write<uint32_t>(0);
464     W.write<uint32_t>(0);
465 
466     // Relocation and line-number counts. Not supported yet.
467     W.write<uint16_t>(0);
468     W.write<uint16_t>(0);
469 
470     W.write<int32_t>(Sec->Flags);
471   }
472 }
473 
474 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
475   // Print out symbol table for the program code.
476   for (const auto &Csect : ProgramCodeCsects) {
477     // Write out the control section first and then each symbol in it.
478     writeSymbolTableEntryForControlSection(Csect, Text.Index,
479                                            Csect.MCCsect->getStorageClass());
480     for (const auto &Sym : Csect.Syms)
481       writeSymbolTableEntryForCsectMemberLabel(
482           Sym, Csect, Text.Index, Layout.getSymbolOffset(*Sym.MCSym));
483   }
484 
485   // The BSS Section is special in that the csects must contain a single symbol,
486   // and the contained symbol cannot be represented in the symbol table as a
487   // label definition.
488   for (auto &Csect : BSSCsects) {
489     assert(Csect.Syms.size() == 1 &&
490            "Uninitialized csect cannot contain more then 1 symbol.");
491     Symbol &Sym = Csect.Syms.back();
492     writeSymbolTableEntryForControlSection(Csect, BSS.Index,
493                                            Sym.getStorageClass());
494   }
495 }
496 
497 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
498   // The address corrresponds to the address of sections and symbols in the
499   // object file. We place the shared address 0 immediately after the
500   // section header table.
501   uint32_t Address = 0;
502   // Section indices are 1-based in XCOFF.
503   int16_t SectionIndex = 1;
504   // The first symbol table entry is for the file name. We are not emitting it
505   // yet, so start at index 0.
506   uint32_t SymbolTableIndex = 0;
507 
508   // Text section comes first.
509   if (!ProgramCodeCsects.empty()) {
510     Sections.push_back(&Text);
511     Text.Index = SectionIndex++;
512     for (auto &Csect : ProgramCodeCsects) {
513       const MCSectionXCOFF *MCSec = Csect.MCCsect;
514       Csect.Address = alignTo(Address, MCSec->getAlignment());
515       Csect.Size = Layout.getSectionAddressSize(MCSec);
516       Address = Csect.Address + Csect.Size;
517       Csect.SymbolTableIndex = SymbolTableIndex;
518       // 1 main and 1 auxiliary symbol table entry for the csect.
519       SymbolTableIndex += 2;
520       for (auto &Sym : Csect.Syms) {
521         Sym.SymbolTableIndex = SymbolTableIndex;
522         // 1 main and 1 auxiliary symbol table entry for each contained symbol
523         SymbolTableIndex += 2;
524       }
525     }
526     Address = alignTo(Address, DefaultSectionAlign);
527 
528     // The first csect of a section can be aligned by adjusting the virtual
529     // address of its containing section instead of writing zeroes into the
530     // object file.
531     Text.Address = ProgramCodeCsects.front().Address;
532 
533     Text.Size = Address - Text.Address;
534   }
535 
536   // Data section Second. TODO
537 
538   // BSS Section third.
539   if (!BSSCsects.empty()) {
540     Sections.push_back(&BSS);
541     BSS.Index = SectionIndex++;
542     for (auto &Csect : BSSCsects) {
543       const MCSectionXCOFF *MCSec = Csect.MCCsect;
544       Csect.Address = alignTo(Address, MCSec->getAlignment());
545       Csect.Size = Layout.getSectionAddressSize(MCSec);
546       Address = Csect.Address + Csect.Size;
547       Csect.SymbolTableIndex = SymbolTableIndex;
548       // 1 main and 1 auxiliary symbol table entry for the csect.
549       SymbolTableIndex += 2;
550 
551       assert(Csect.Syms.size() == 1 &&
552              "csect in the BSS can only contain a single symbol.");
553       Csect.Syms[0].SymbolTableIndex = Csect.SymbolTableIndex;
554     }
555     // Pad out Address to the default alignment. This is to match how the system
556     // assembler handles the .bss section. Its size is always a multiple of 4.
557     Address = alignTo(Address, DefaultSectionAlign);
558 
559     BSS.Address = BSSCsects.front().Address;
560     BSS.Size = Address - BSS.Address;
561   }
562 
563   SymbolTableEntryCount = SymbolTableIndex;
564 
565   // Calculate the RawPointer value for each section.
566   uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() +
567                         Sections.size() * sizeof(XCOFF::SectionHeader32);
568   for (auto *Sec : Sections) {
569     if (!Sec->IsVirtual) {
570       Sec->FileOffsetToData = RawPointer;
571       RawPointer += Sec->Size;
572     }
573   }
574 
575   // TODO Add in Relocation storage to the RawPointer Calculation.
576   // TODO What to align the SymbolTable to?
577   // TODO Error check that the number of symbol table entries fits in 32-bits
578   // signed ...
579   if (SymbolTableEntryCount)
580     SymbolTableOffset = RawPointer;
581 }
582 
583 // Takes the log base 2 of the alignment and shifts the result into the 5 most
584 // significant bits of a byte, then or's in the csect type into the least
585 // significant 3 bits.
586 uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
587   unsigned Align = Sec->getAlignment();
588   assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.");
589   unsigned Log2Align = Log2_32(Align);
590   // Result is a number in the range [0, 31] which fits in the 5 least
591   // significant bits. Shift this value into the 5 most significant bits, and
592   // bitwise-or in the csect type.
593   uint8_t EncodedAlign = Log2Align << 3;
594   return EncodedAlign | Sec->getCSectType();
595 }
596 
597 } // end anonymous namespace
598 
599 std::unique_ptr<MCObjectWriter>
600 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
601                               raw_pwrite_stream &OS) {
602   return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
603 }
604