1//===- MCAsmInfoCOFF.cpp - COFF asm properties ----------------------------===//
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 defines target asm properties related what form asm statements
10// should take in general on COFF-based targets
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/MC/MCAsmInfoCOFF.h"
15#include "llvm/BinaryFormat/COFF.h"
16#include "llvm/MC/MCDirectives.h"
17#include "llvm/MC/MCSection.h"
18#include "llvm/MC/MCSectionCOFF.h"
19#include "llvm/MC/MCSymbol.h"
20#include "llvm/Support/raw_ostream.h"
21#include <cassert>
22
23using namespace llvm;
24
25void MCAsmInfoCOFF::anchor() {}
26
27MCAsmInfoCOFF::MCAsmInfoCOFF() {
28 // MingW 4.5 and later support .comm with log2 alignment, but .lcomm uses byte
29 // alignment.
30 COMMDirectiveAlignmentIsInBytes = false;
31 LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
32 HasDotTypeDotSizeDirective = false;
33 HasSingleParameterDotFile = true;
34 WeakRefDirective = "\t.weak\t";
35 AvoidWeakIfComdat = true;
36
37 // Doesn't support visibility:
38 HiddenVisibilityAttr = HiddenDeclarationVisibilityAttr = MCSA_Invalid;
39 ProtectedVisibilityAttr = MCSA_Invalid;
40
41 // Set up DWARF directives
42 SupportsDebugInformation = true;
43 NeedsDwarfSectionOffsetDirective = true;
44
45 // At least MSVC inline-asm does AShr.
46 UseLogicalShr = false;
47
48 // If this is a COFF target, assume that it supports associative comdats. It's
49 // part of the spec.
50 HasCOFFAssociativeComdats = true;
51
52 // We can generate constants in comdat sections that can be shared,
53 // but in order not to create null typed symbols, we actually need to
54 // make them global symbols as well.
55 HasCOFFComdatConstants = true;
56}
57
58bool MCAsmInfoCOFF::useCodeAlign(const MCSection &Sec) const {
59 return Sec.isText();
60}
61
62void MCAsmInfoMicrosoft::anchor() {}
63
64MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() = default;
65
66void MCAsmInfoGNUCOFF::anchor() {}
67
68MCAsmInfoGNUCOFF::MCAsmInfoGNUCOFF() {
69 // If this is a GNU environment (mingw or cygwin), don't use associative
70 // comdats for jump tables, unwind information, and other data associated with
71 // a function.
72 HasCOFFAssociativeComdats = false;
73
74 // We don't create constants in comdat sections for MinGW.
75 HasCOFFComdatConstants = false;
76}
77
78bool MCSectionCOFF::shouldOmitSectionDirective(StringRef Name) const {
79 if (COMDATSymbol || isUnique())
80 return false;
81
82 // FIXME: Does .section .bss/.data/.text work everywhere??
83 if (Name == ".text" || Name == ".data" || Name == ".bss")
84 return true;
85
86 return false;
87}
88
89void MCSectionCOFF::setSelection(int Selection) const {
90 assert(Selection != 0 && "invalid COMDAT selection type");
91 this->Selection = Selection;
92 Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
93}
94
95void MCAsmInfoCOFF::printSwitchToSection(const MCSection &Section, uint32_t,
96 const Triple &T,
97 raw_ostream &OS) const {
98 auto &Sec = static_cast<const MCSectionCOFF &>(Section);
99 // standard sections don't require the '.section'
100 if (Sec.shouldOmitSectionDirective(Name: Sec.getName())) {
101 OS << '\t' << Sec.getName() << '\n';
102 return;
103 }
104
105 OS << "\t.section\t" << Sec.getName() << ",\"";
106 if (Sec.getCharacteristics() & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
107 OS << 'd';
108 if (Sec.getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
109 OS << 'b';
110 if (Sec.getCharacteristics() & COFF::IMAGE_SCN_MEM_EXECUTE)
111 OS << 'x';
112 if (Sec.getCharacteristics() & COFF::IMAGE_SCN_MEM_WRITE)
113 OS << 'w';
114 else if (Sec.getCharacteristics() & COFF::IMAGE_SCN_MEM_READ)
115 OS << 'r';
116 else
117 OS << 'y';
118 if (Sec.getCharacteristics() & COFF::IMAGE_SCN_LNK_REMOVE)
119 OS << 'n';
120 if (Sec.getCharacteristics() & COFF::IMAGE_SCN_MEM_SHARED)
121 OS << 's';
122 if ((Sec.getCharacteristics() & COFF::IMAGE_SCN_MEM_DISCARDABLE) &&
123 !Sec.isImplicitlyDiscardable(Name: Sec.getName()))
124 OS << 'D';
125 if (Sec.getCharacteristics() & COFF::IMAGE_SCN_LNK_INFO)
126 OS << 'i';
127 OS << '"';
128
129 // unique should be tail of .section directive.
130 if (Sec.isUnique() && !Sec.COMDATSymbol)
131 OS << ",unique," << Sec.UniqueID;
132
133 if (Sec.getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
134 if (Sec.COMDATSymbol)
135 OS << ",";
136 else
137 OS << "\n\t.linkonce\t";
138 switch (Sec.Selection) {
139 case COFF::IMAGE_COMDAT_SELECT_NODUPLICATES:
140 OS << "one_only";
141 break;
142 case COFF::IMAGE_COMDAT_SELECT_ANY:
143 OS << "discard";
144 break;
145 case COFF::IMAGE_COMDAT_SELECT_SAME_SIZE:
146 OS << "same_size";
147 break;
148 case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH:
149 OS << "same_contents";
150 break;
151 case COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE:
152 OS << "associative";
153 break;
154 case COFF::IMAGE_COMDAT_SELECT_LARGEST:
155 OS << "largest";
156 break;
157 case COFF::IMAGE_COMDAT_SELECT_NEWEST:
158 OS << "newest";
159 break;
160 default:
161 assert(false && "unsupported COFF selection type");
162 break;
163 }
164 if (Sec.COMDATSymbol) {
165 OS << ",";
166 Sec.COMDATSymbol->print(OS, MAI: this);
167 }
168 }
169
170 if (Sec.isUnique() && Sec.COMDATSymbol)
171 OS << ",unique," << Sec.UniqueID;
172
173 OS << '\n';
174}
175