//===- MCAsmInfoCOFF.cpp - COFF asm properties ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines target asm properties related what form asm statements // should take in general on COFF-based targets // //===----------------------------------------------------------------------===// #include "llvm/MC/MCAsmInfoCOFF.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/raw_ostream.h" #include using namespace llvm; void MCAsmInfoCOFF::anchor() {} MCAsmInfoCOFF::MCAsmInfoCOFF() { // MingW 4.5 and later support .comm with log2 alignment, but .lcomm uses byte // alignment. COMMDirectiveAlignmentIsInBytes = false; LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment; HasDotTypeDotSizeDirective = false; HasSingleParameterDotFile = true; WeakRefDirective = "\t.weak\t"; AvoidWeakIfComdat = true; // Doesn't support visibility: HiddenVisibilityAttr = HiddenDeclarationVisibilityAttr = MCSA_Invalid; ProtectedVisibilityAttr = MCSA_Invalid; // Set up DWARF directives SupportsDebugInformation = true; NeedsDwarfSectionOffsetDirective = true; // At least MSVC inline-asm does AShr. UseLogicalShr = false; // If this is a COFF target, assume that it supports associative comdats. It's // part of the spec. HasCOFFAssociativeComdats = true; // We can generate constants in comdat sections that can be shared, // but in order not to create null typed symbols, we actually need to // make them global symbols as well. HasCOFFComdatConstants = true; } bool MCAsmInfoCOFF::useCodeAlign(const MCSection &Sec) const { return Sec.isText(); } void MCAsmInfoMicrosoft::anchor() {} MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() = default; void MCAsmInfoGNUCOFF::anchor() {} MCAsmInfoGNUCOFF::MCAsmInfoGNUCOFF() { // If this is a GNU environment (mingw or cygwin), don't use associative // comdats for jump tables, unwind information, and other data associated with // a function. HasCOFFAssociativeComdats = false; // We don't create constants in comdat sections for MinGW. HasCOFFComdatConstants = false; } bool MCSectionCOFF::shouldOmitSectionDirective(StringRef Name) const { if (COMDATSymbol || isUnique()) return false; // FIXME: Does .section .bss/.data/.text work everywhere?? if (Name == ".text" || Name == ".data" || Name == ".bss") return true; return false; } void MCSectionCOFF::setSelection(int Selection) const { assert(Selection != 0 && "invalid COMDAT selection type"); this->Selection = Selection; Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; } void MCAsmInfoCOFF::printSwitchToSection(const MCSection &Section, uint32_t, const Triple &T, raw_ostream &OS) const { auto &Sec = static_cast(Section); // standard sections don't require the '.section' if (Sec.shouldOmitSectionDirective(Sec.getName())) { OS << '\t' << Sec.getName() << '\n'; return; } OS << "\t.section\t" << Sec.getName() << ",\""; if (Sec.getCharacteristics() & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) OS << 'd'; if (Sec.getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) OS << 'b'; if (Sec.getCharacteristics() & COFF::IMAGE_SCN_MEM_EXECUTE) OS << 'x'; if (Sec.getCharacteristics() & COFF::IMAGE_SCN_MEM_WRITE) OS << 'w'; else if (Sec.getCharacteristics() & COFF::IMAGE_SCN_MEM_READ) OS << 'r'; else OS << 'y'; if (Sec.getCharacteristics() & COFF::IMAGE_SCN_LNK_REMOVE) OS << 'n'; if (Sec.getCharacteristics() & COFF::IMAGE_SCN_MEM_SHARED) OS << 's'; if ((Sec.getCharacteristics() & COFF::IMAGE_SCN_MEM_DISCARDABLE) && !Sec.isImplicitlyDiscardable(Sec.getName())) OS << 'D'; if (Sec.getCharacteristics() & COFF::IMAGE_SCN_LNK_INFO) OS << 'i'; OS << '"'; // unique should be tail of .section directive. if (Sec.isUnique() && !Sec.COMDATSymbol) OS << ",unique," << Sec.UniqueID; if (Sec.getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { if (Sec.COMDATSymbol) OS << ","; else OS << "\n\t.linkonce\t"; switch (Sec.Selection) { case COFF::IMAGE_COMDAT_SELECT_NODUPLICATES: OS << "one_only"; break; case COFF::IMAGE_COMDAT_SELECT_ANY: OS << "discard"; break; case COFF::IMAGE_COMDAT_SELECT_SAME_SIZE: OS << "same_size"; break; case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH: OS << "same_contents"; break; case COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE: OS << "associative"; break; case COFF::IMAGE_COMDAT_SELECT_LARGEST: OS << "largest"; break; case COFF::IMAGE_COMDAT_SELECT_NEWEST: OS << "newest"; break; default: assert(false && "unsupported COFF selection type"); break; } if (Sec.COMDATSymbol) { OS << ","; Sec.COMDATSymbol->print(OS, this); } } if (Sec.isUnique() && Sec.COMDATSymbol) OS << ",unique," << Sec.UniqueID; OS << '\n'; }