1 | //===-- PPCMCAsmInfo.cpp - PPC 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 MCAsmInfoDarwin properties. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "MCTargetDesc/PPCMCAsmInfo.h" |
14 | #include "llvm/MC/MCExpr.h" |
15 | #include "llvm/Support/raw_ostream.h" |
16 | #include "llvm/TargetParser/Triple.h" |
17 | |
18 | using namespace llvm; |
19 | |
20 | void PPCELFMCAsmInfo::anchor() { } |
21 | |
22 | const MCAsmInfo::AtSpecifier elfAtSpecifiers[] = { |
23 | {.Kind: PPC::S_DTPREL, .Name: "DTPREL" }, |
24 | {.Kind: PPC::S_GOT, .Name: "GOT" }, |
25 | {.Kind: PPC::S_GOT_HA, .Name: "got@ha" }, |
26 | {.Kind: PPC::S_GOT_HI, .Name: "got@h" }, |
27 | {.Kind: PPC::S_GOT_LO, .Name: "got@l" }, |
28 | {.Kind: PPC::S_HA, .Name: "ha" }, |
29 | {.Kind: PPC::S_HI, .Name: "h" }, |
30 | {.Kind: PPC::S_HIGH, .Name: "high" }, |
31 | {.Kind: PPC::S_HIGHA, .Name: "higha" }, |
32 | {.Kind: PPC::S_HIGHER, .Name: "higher" }, |
33 | {.Kind: PPC::S_HIGHERA, .Name: "highera" }, |
34 | {.Kind: PPC::S_HIGHEST, .Name: "highest" }, |
35 | {.Kind: PPC::S_HIGHESTA, .Name: "highesta" }, |
36 | {.Kind: PPC::S_LO, .Name: "l" }, |
37 | {.Kind: PPC::S_PCREL, .Name: "PCREL" }, |
38 | {.Kind: PPC::S_PLT, .Name: "PLT" }, |
39 | {.Kind: PPC::S_TLSGD, .Name: "tlsgd" }, |
40 | {.Kind: PPC::S_TLSLD, .Name: "tlsld" }, |
41 | {.Kind: PPC::S_TOC, .Name: "toc" }, |
42 | {.Kind: PPC::S_TOCBASE, .Name: "tocbase" }, |
43 | {.Kind: PPC::S_TOC_HA, .Name: "toc@ha" }, |
44 | {.Kind: PPC::S_TOC_HI, .Name: "toc@h" }, |
45 | {.Kind: PPC::S_TOC_LO, .Name: "toc@l" }, |
46 | {.Kind: PPC::S_TPREL, .Name: "TPREL" }, |
47 | {.Kind: PPC::S_AIX_TLSGD, .Name: "gd" }, |
48 | {.Kind: PPC::S_AIX_TLSGDM, .Name: "m" }, |
49 | {.Kind: PPC::S_AIX_TLSIE, .Name: "ie" }, |
50 | {.Kind: PPC::S_AIX_TLSLD, .Name: "ld" }, |
51 | {.Kind: PPC::S_AIX_TLSLE, .Name: "le" }, |
52 | {.Kind: PPC::S_AIX_TLSML, .Name: "ml" }, |
53 | {.Kind: PPC::S_DTPMOD, .Name: "dtpmod" }, |
54 | {.Kind: PPC::S_DTPREL_HA, .Name: "dtprel@ha" }, |
55 | {.Kind: PPC::S_DTPREL_HI, .Name: "dtprel@h" }, |
56 | {.Kind: PPC::S_DTPREL_HIGH, .Name: "dtprel@high" }, |
57 | {.Kind: PPC::S_DTPREL_HIGHA, .Name: "dtprel@higha" }, |
58 | {.Kind: PPC::S_DTPREL_HIGHER, .Name: "dtprel@higher" }, |
59 | {.Kind: PPC::S_DTPREL_HIGHERA, .Name: "dtprel@highera" }, |
60 | {.Kind: PPC::S_DTPREL_HIGHEST, .Name: "dtprel@highest" }, |
61 | {.Kind: PPC::S_DTPREL_HIGHESTA, .Name: "dtprel@highesta" }, |
62 | {.Kind: PPC::S_DTPREL_LO, .Name: "dtprel@l" }, |
63 | {.Kind: PPC::S_GOT_DTPREL, .Name: "got@dtprel" }, |
64 | {.Kind: PPC::S_GOT_DTPREL_HA, .Name: "got@dtprel@ha" }, |
65 | {.Kind: PPC::S_GOT_DTPREL_HI, .Name: "got@dtprel@h" }, |
66 | {.Kind: PPC::S_GOT_DTPREL_LO, .Name: "got@dtprel@l" }, |
67 | {.Kind: PPC::S_GOT_PCREL, .Name: "got@pcrel" }, |
68 | {.Kind: PPC::S_GOT_TLSGD, .Name: "got@tlsgd" }, |
69 | {.Kind: PPC::S_GOT_TLSGD_HA, .Name: "got@tlsgd@ha" }, |
70 | {.Kind: PPC::S_GOT_TLSGD_HI, .Name: "got@tlsgd@h" }, |
71 | {.Kind: PPC::S_GOT_TLSGD_LO, .Name: "got@tlsgd@l" }, |
72 | {.Kind: PPC::S_GOT_TLSGD_PCREL, .Name: "got@tlsgd@pcrel" }, |
73 | {.Kind: PPC::S_GOT_TLSLD, .Name: "got@tlsld" }, |
74 | {.Kind: PPC::S_GOT_TLSLD_HA, .Name: "got@tlsld@ha" }, |
75 | {.Kind: PPC::S_GOT_TLSLD_HI, .Name: "got@tlsld@h" }, |
76 | {.Kind: PPC::S_GOT_TLSLD_LO, .Name: "got@tlsld@l" }, |
77 | {.Kind: PPC::S_GOT_TLSLD_PCREL, .Name: "got@tlsld@pcrel" }, |
78 | {.Kind: PPC::S_GOT_TPREL, .Name: "got@tprel" }, |
79 | {.Kind: PPC::S_GOT_TPREL_HA, .Name: "got@tprel@ha" }, |
80 | {.Kind: PPC::S_GOT_TPREL_HI, .Name: "got@tprel@h" }, |
81 | {.Kind: PPC::S_GOT_TPREL_LO, .Name: "got@tprel@l" }, |
82 | {.Kind: PPC::S_GOT_TPREL_PCREL, .Name: "got@tprel@pcrel" }, |
83 | {.Kind: PPC::S_LOCAL, .Name: "local" }, |
84 | {.Kind: PPC::S_NOTOC, .Name: "notoc" }, |
85 | {.Kind: PPC::S_PCREL_OPT, .Name: "<<invalid>>" }, |
86 | {.Kind: PPC::S_TLS, .Name: "tls" }, |
87 | {.Kind: PPC::S_TLS_PCREL, .Name: "tls@pcrel" }, |
88 | {.Kind: PPC::S_TPREL_HA, .Name: "tprel@ha" }, |
89 | {.Kind: PPC::S_TPREL_HI, .Name: "tprel@h" }, |
90 | {.Kind: PPC::S_TPREL_HIGH, .Name: "tprel@high" }, |
91 | {.Kind: PPC::S_TPREL_HIGHA, .Name: "tprel@higha" }, |
92 | {.Kind: PPC::S_TPREL_HIGHER, .Name: "tprel@higher" }, |
93 | {.Kind: PPC::S_TPREL_HIGHERA, .Name: "tprel@highera" }, |
94 | {.Kind: PPC::S_TPREL_HIGHEST, .Name: "tprel@highest" }, |
95 | {.Kind: PPC::S_TPREL_HIGHESTA, .Name: "tprel@highesta" }, |
96 | {.Kind: PPC::S_TPREL_LO, .Name: "tprel@l" }, |
97 | }; |
98 | |
99 | const MCAsmInfo::AtSpecifier xcoffAtSpecifiers[] = { |
100 | // clang-format off |
101 | {.Kind: PPC::S_AIX_TLSGD, .Name: "gd" }, |
102 | {.Kind: PPC::S_AIX_TLSGDM, .Name: "m" }, |
103 | {.Kind: PPC::S_AIX_TLSIE, .Name: "ie" }, |
104 | {.Kind: PPC::S_AIX_TLSLD, .Name: "ld" }, |
105 | {.Kind: PPC::S_AIX_TLSLE, .Name: "le" }, |
106 | {.Kind: PPC::S_AIX_TLSML, .Name: "ml" }, |
107 | {.Kind: PPC::S_L, .Name: "l" }, |
108 | {.Kind: PPC::S_U, .Name: "u" }, |
109 | // clang-format on |
110 | }; |
111 | |
112 | static std::optional<int64_t> evaluateAsInt64(uint16_t specifier, |
113 | int64_t Value) { |
114 | switch (specifier) { |
115 | case PPC::S_LO: |
116 | return Value & 0xffff; |
117 | case PPC::S_HI: |
118 | return (Value >> 16) & 0xffff; |
119 | case PPC::S_HA: |
120 | return ((Value + 0x8000) >> 16) & 0xffff; |
121 | case PPC::S_HIGH: |
122 | return (Value >> 16) & 0xffff; |
123 | case PPC::S_HIGHA: |
124 | return ((Value + 0x8000) >> 16) & 0xffff; |
125 | case PPC::S_HIGHER: |
126 | return (Value >> 32) & 0xffff; |
127 | case PPC::S_HIGHERA: |
128 | return ((Value + 0x8000) >> 32) & 0xffff; |
129 | case PPC::S_HIGHEST: |
130 | return (Value >> 48) & 0xffff; |
131 | case PPC::S_HIGHESTA: |
132 | return ((Value + 0x8000) >> 48) & 0xffff; |
133 | default: |
134 | return {}; |
135 | } |
136 | } |
137 | |
138 | bool PPC::evaluateAsConstant(const MCSpecifierExpr &Expr, int64_t &Res) { |
139 | MCValue Value; |
140 | |
141 | if (!Expr.getSubExpr()->evaluateAsRelocatable(Res&: Value, Asm: nullptr)) |
142 | return false; |
143 | |
144 | if (!Value.isAbsolute()) |
145 | return false; |
146 | auto Tmp = evaluateAsInt64(specifier: Expr.getSpecifier(), Value: Value.getConstant()); |
147 | if (!Tmp) |
148 | return false; |
149 | Res = *Tmp; |
150 | return true; |
151 | } |
152 | |
153 | static bool evaluateAsRelocatable(const MCSpecifierExpr &Expr, MCValue &Res, |
154 | const MCAssembler *Asm) { |
155 | if (!Expr.getSubExpr()->evaluateAsRelocatable(Res, Asm)) |
156 | return false; |
157 | |
158 | // The signedness of the result is dependent on the instruction operand. E.g. |
159 | // in addis 3,3,65535@l, 65535@l is signed. In the absence of information at |
160 | // parse time (!Asm), disable the folding. |
161 | std::optional<int64_t> MaybeInt = |
162 | evaluateAsInt64(specifier: Expr.getSpecifier(), Value: Res.getConstant()); |
163 | if (Res.isAbsolute() && MaybeInt) { |
164 | Res = MCValue::get(Val: *MaybeInt); |
165 | } else { |
166 | Res.setSpecifier(Expr.getSpecifier()); |
167 | } |
168 | |
169 | return true; |
170 | } |
171 | |
172 | PPCELFMCAsmInfo::PPCELFMCAsmInfo(bool is64Bit, const Triple& T) { |
173 | // FIXME: This is not always needed. For example, it is not needed in the |
174 | // v2 abi. |
175 | NeedsLocalForSize = true; |
176 | |
177 | if (is64Bit) { |
178 | CodePointerSize = CalleeSaveStackSlotSize = 8; |
179 | } |
180 | IsLittleEndian = |
181 | T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle; |
182 | |
183 | // ".comm align is in bytes but .align is pow-2." |
184 | AlignmentIsInBytes = false; |
185 | |
186 | CommentString = "#" ; |
187 | |
188 | // Uses '.section' before '.bss' directive |
189 | UsesELFSectionDirectiveForBSS = true; |
190 | |
191 | // Debug Information |
192 | SupportsDebugInformation = true; |
193 | |
194 | DollarIsPC = true; |
195 | |
196 | // Set up DWARF directives |
197 | MinInstAlignment = 4; |
198 | |
199 | // Exceptions handling |
200 | ExceptionsType = ExceptionHandling::DwarfCFI; |
201 | |
202 | ZeroDirective = "\t.space\t" ; |
203 | Data64bitsDirective = is64Bit ? "\t.quad\t" : nullptr; |
204 | AssemblerDialect = 1; // New-Style mnemonics. |
205 | LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment; |
206 | |
207 | initializeAtSpecifiers(elfAtSpecifiers); |
208 | } |
209 | |
210 | void PPCELFMCAsmInfo::printSpecifierExpr(raw_ostream &OS, |
211 | const MCSpecifierExpr &Expr) const { |
212 | printExpr(OS, *Expr.getSubExpr()); |
213 | OS << '@' << getSpecifierName(S: Expr.getSpecifier()); |
214 | } |
215 | |
216 | bool PPCELFMCAsmInfo::evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, |
217 | MCValue &Res, |
218 | const MCAssembler *Asm) const { |
219 | return evaluateAsRelocatable(Expr, Res, Asm); |
220 | } |
221 | |
222 | void PPCXCOFFMCAsmInfo::anchor() {} |
223 | |
224 | PPCXCOFFMCAsmInfo::PPCXCOFFMCAsmInfo(bool Is64Bit, const Triple &T) { |
225 | if (T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle) |
226 | report_fatal_error(reason: "XCOFF is not supported for little-endian targets" ); |
227 | CodePointerSize = CalleeSaveStackSlotSize = Is64Bit ? 8 : 4; |
228 | |
229 | // A size of 8 is only supported by the assembler under 64-bit. |
230 | Data64bitsDirective = Is64Bit ? "\t.vbyte\t8, " : nullptr; |
231 | |
232 | // Debug Information |
233 | SupportsDebugInformation = true; |
234 | |
235 | // Set up DWARF directives |
236 | MinInstAlignment = 4; |
237 | |
238 | // Support $ as PC in inline asm |
239 | DollarIsPC = true; |
240 | |
241 | UsesSetToEquateSymbol = true; |
242 | |
243 | initializeAtSpecifiers(xcoffAtSpecifiers); |
244 | } |
245 | |
246 | void PPCXCOFFMCAsmInfo::printSpecifierExpr(raw_ostream &OS, |
247 | const MCSpecifierExpr &Expr) const { |
248 | printExpr(OS, *Expr.getSubExpr()); |
249 | OS << '@' << getSpecifierName(S: Expr.getSpecifier()); |
250 | } |
251 | |
252 | bool PPCXCOFFMCAsmInfo::evaluateAsRelocatableImpl( |
253 | const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const { |
254 | return evaluateAsRelocatable(Expr, Res, Asm); |
255 | } |
256 | |