1//===-- X86MCAsmInfo.cpp - X86 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 contains the declarations of the X86MCAsmInfo properties.
10//
11//===----------------------------------------------------------------------===//
12
13#include "X86MCAsmInfo.h"
14#include "llvm/ADT/Enum.h"
15#include "llvm/MC/MCExpr.h"
16#include "llvm/MC/MCStreamer.h"
17#include "llvm/Support/CommandLine.h"
18#include "llvm/TargetParser/Triple.h"
19using namespace llvm;
20
21enum AsmWriterFlavorTy {
22 // Note: This numbering has to match the GCC assembler dialects for inline
23 // asm alternatives to work right.
24 ATT = 0, Intel = 1
25};
26
27static cl::opt<AsmWriterFlavorTy> X86AsmSyntax(
28 "x86-asm-syntax", cl::init(Val: ATT), cl::Hidden,
29 cl::desc("Select the assembly style for input"),
30 cl::values(clEnumValN(ATT, "att", "Emit AT&T-style assembly"),
31 clEnumValN(Intel, "intel", "Emit Intel-style assembly")));
32
33static cl::opt<bool>
34MarkedJTDataRegions("mark-data-regions", cl::init(Val: true),
35 cl::desc("Mark code section jump table data regions."),
36 cl::Hidden);
37
38constexpr EnumStringDef<MCAsmInfo::AtSpecifierKind> AtSpecifierDefs[] = {
39 {.Names: {"ABS8"}, .Value: X86::S_ABS8},
40 {.Names: {"DTPOFF"}, .Value: X86::S_DTPOFF},
41 {.Names: {"DTPREL"}, .Value: X86::S_DTPREL},
42 {.Names: {"GOT"}, .Value: X86::S_GOT},
43 {.Names: {"GOTENT"}, .Value: X86::S_GOTENT},
44 {.Names: {"GOTNTPOFF"}, .Value: X86::S_GOTNTPOFF},
45 {.Names: {"GOTOFF"}, .Value: X86::S_GOTOFF},
46 {.Names: {"GOTPCREL"}, .Value: X86::S_GOTPCREL},
47 {.Names: {"GOTPCREL_NORELAX"}, .Value: X86::S_GOTPCREL_NORELAX},
48 {.Names: {"GOTREL"}, .Value: X86::S_GOTREL},
49 {.Names: {"GOTTPOFF"}, .Value: X86::S_GOTTPOFF},
50 {.Names: {"INDNTPOFF"}, .Value: X86::S_INDNTPOFF},
51 {.Names: {"IMGREL"}, .Value: MCSymbolRefExpr::VK_COFF_IMGREL32},
52 {.Names: {"NTPOFF"}, .Value: X86::S_NTPOFF},
53 {.Names: {"PCREL"}, .Value: X86::S_PCREL},
54 {.Names: {"PLT"}, .Value: X86::S_PLT},
55 {.Names: {"PLTOFF"}, .Value: X86::S_PLTOFF},
56 {.Names: {"SECREL32"}, .Value: X86::S_COFF_SECREL},
57 {.Names: {"SIZE"}, .Value: X86::S_SIZE},
58 {.Names: {"tlscall"}, .Value: X86::S_TLSCALL},
59 {.Names: {"tlsdesc"}, .Value: X86::S_TLSDESC},
60 {.Names: {"TLSGD"}, .Value: X86::S_TLSGD},
61 {.Names: {"TLSLD"}, .Value: X86::S_TLSLD},
62 {.Names: {"TLSLDM"}, .Value: X86::S_TLSLDM},
63 {.Names: {"TLVP"}, .Value: X86::S_TLVP},
64 {.Names: {"TLVPPAGE"}, .Value: X86::S_TLVPPAGE},
65 {.Names: {"TLVPPAGEOFF"}, .Value: X86::S_TLVPPAGEOFF},
66 {.Names: {"TPOFF"}, .Value: X86::S_TPOFF},
67};
68constexpr auto atSpecifiers = BUILD_ENUM_STRINGS(AtSpecifierDefs);
69
70void X86MCAsmInfoDarwin::anchor() { }
71
72X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T,
73 const MCTargetOptions &Options)
74 : MCAsmInfoDarwin(Options) {
75 bool is64Bit = T.isX86_64();
76 if (is64Bit)
77 CodePointerSize = CalleeSaveStackSlotSize = 8;
78
79 AssemblerDialect = X86AsmSyntax;
80
81 if (!is64Bit)
82 Data64bitsDirective = nullptr; // we can't emit a 64-bit unit
83
84 // Use ## as a comment string so that .s files generated by llvm can go
85 // through the GCC preprocessor without causing an error. This is needed
86 // because "clang foo.s" runs the C preprocessor, which is usually reserved
87 // for .S files on other systems. Perhaps this is because the file system
88 // wasn't always case preserving or something.
89 CommentString = "##";
90
91 SupportsDebugInformation = true;
92 UseDataRegionDirectives = MarkedJTDataRegions;
93
94 // Exceptions handling
95 ExceptionsType = ExceptionHandling::DwarfCFI;
96
97 // old assembler lacks some directives
98 // FIXME: this should really be a check on the assembler characteristics
99 // rather than OS version
100 if (T.isMacOSX() && T.isMacOSXVersionLT(Major: 10, Minor: 6))
101 HasWeakDefCanBeHiddenDirective = false;
102
103 // Assume ld64 is new enough that the abs-ified FDE relocs may be used
104 // (actually, must, since otherwise the non-extern relocations we produce
105 // overwhelm ld64's tiny little mind and it fails).
106 DwarfFDESymbolsUseAbsDiff = true;
107
108 initializeAtSpecifiers(atSpecifiers);
109}
110
111X86_64MCAsmInfoDarwin::X86_64MCAsmInfoDarwin(const Triple &Triple,
112 const MCTargetOptions &Options)
113 : X86MCAsmInfoDarwin(Triple, Options) {}
114
115void X86ELFMCAsmInfo::anchor() { }
116
117X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T,
118 const MCTargetOptions &Options)
119 : MCAsmInfoELF(Options) {
120 bool is64Bit = T.isX86_64();
121 bool isX32 = T.isX32();
122
123 // For ELF, x86-64 pointer size depends on the ABI.
124 // For x86-64 without the x32 ABI, pointer size is 8. For x86 and for x86-64
125 // with the x32 ABI, pointer size remains the default 4.
126 CodePointerSize = (is64Bit && !isX32) ? 8 : 4;
127
128 // OTOH, stack slot size is always 8 for x86-64, even with the x32 ABI.
129 CalleeSaveStackSlotSize = is64Bit ? 8 : 4;
130
131 AssemblerDialect = X86AsmSyntax;
132
133 // Debug Information
134 SupportsDebugInformation = true;
135
136 // Exceptions handling
137 ExceptionsType = ExceptionHandling::DwarfCFI;
138
139 initializeAtSpecifiers(atSpecifiers);
140}
141
142const MCExpr *
143X86_64MCAsmInfoDarwin::getExprForPersonalitySymbol(const MCSymbol *Sym,
144 unsigned Encoding,
145 MCStreamer &Streamer) const {
146 MCContext &Context = Streamer.getContext();
147 const MCExpr *Res = MCSymbolRefExpr::create(Symbol: Sym, specifier: X86::S_GOTPCREL, Ctx&: Context);
148 const MCExpr *Four = MCConstantExpr::create(Value: 4, Ctx&: Context);
149 return MCBinaryExpr::createAdd(LHS: Res, RHS: Four, Ctx&: Context);
150}
151
152void X86MCAsmInfoMicrosoft::anchor() { }
153
154X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple &Triple,
155 const MCTargetOptions &Options)
156 : MCAsmInfoMicrosoft(Options) {
157 if (Triple.isX86_64()) {
158 InternalSymbolPrefix = ".L";
159 CodePointerSize = 8;
160 WinEHEncodingType = WinEH::EncodingType::Itanium;
161 } else {
162 // 32-bit X86 doesn't use CFI, so this isn't a real encoding type. It's just
163 // a place holder that the Windows EHStreamer looks for to suppress CFI
164 // output. In particular, usesWindowsCFI() returns false.
165 WinEHEncodingType = WinEH::EncodingType::X86;
166 }
167
168 ExceptionsType = ExceptionHandling::WinEH;
169
170 AssemblerDialect = X86AsmSyntax;
171
172 AllowAtInName = true;
173
174 initializeAtSpecifiers(atSpecifiers);
175}
176
177void X86MCAsmInfoMicrosoftMASM::anchor() { }
178
179X86MCAsmInfoMicrosoftMASM::X86MCAsmInfoMicrosoftMASM(
180 const Triple &Triple, const MCTargetOptions &Options)
181 : X86MCAsmInfoMicrosoft(Triple, Options) {
182 DollarIsPC = true;
183 SeparatorString = "\n";
184 CommentString = ";";
185 AllowAdditionalComments = false;
186 AllowQuestionAtStartOfIdentifier = true;
187 AllowDollarAtStartOfIdentifier = true;
188 AllowAtAtStartOfIdentifier = true;
189}
190
191void X86MCAsmInfoGNUCOFF::anchor() { }
192
193X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple,
194 const MCTargetOptions &Options)
195 : MCAsmInfoGNUCOFF(Options) {
196 assert(Triple.isOSWindowsOrUEFI() &&
197 "Windows and UEFI are the only supported COFF targets");
198 if (Triple.isX86_64()) {
199 InternalSymbolPrefix = ".L";
200 CodePointerSize = 8;
201 WinEHEncodingType = WinEH::EncodingType::Itanium;
202 ExceptionsType = ExceptionHandling::WinEH;
203 } else {
204 ExceptionsType = ExceptionHandling::DwarfCFI;
205 }
206
207 AssemblerDialect = X86AsmSyntax;
208
209 AllowAtInName = true;
210
211 initializeAtSpecifiers(atSpecifiers);
212}
213