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