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