xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
anchor()20 void PPCELFMCAsmInfo::anchor() { }
21 
22 const MCAsmInfo::AtSpecifier elfAtSpecifiers[] = {
23     {PPC::S_DTPREL, "DTPREL"},
24     {PPC::S_GOT, "GOT"},
25     {PPC::S_GOT_HA, "got@ha"},
26     {PPC::S_GOT_HI, "got@h"},
27     {PPC::S_GOT_LO, "got@l"},
28     {PPC::S_HA, "ha"},
29     {PPC::S_HI, "h"},
30     {PPC::S_HIGH, "high"},
31     {PPC::S_HIGHA, "higha"},
32     {PPC::S_HIGHER, "higher"},
33     {PPC::S_HIGHERA, "highera"},
34     {PPC::S_HIGHEST, "highest"},
35     {PPC::S_HIGHESTA, "highesta"},
36     {PPC::S_LO, "l"},
37     {PPC::S_PCREL, "PCREL"},
38     {PPC::S_PLT, "PLT"},
39     {PPC::S_TLSGD, "tlsgd"},
40     {PPC::S_TLSLD, "tlsld"},
41     {PPC::S_TOC, "toc"},
42     {PPC::S_TOCBASE, "tocbase"},
43     {PPC::S_TOC_HA, "toc@ha"},
44     {PPC::S_TOC_HI, "toc@h"},
45     {PPC::S_TOC_LO, "toc@l"},
46     {PPC::S_TPREL, "TPREL"},
47     {PPC::S_AIX_TLSGD, "gd"},
48     {PPC::S_AIX_TLSGDM, "m"},
49     {PPC::S_AIX_TLSIE, "ie"},
50     {PPC::S_AIX_TLSLD, "ld"},
51     {PPC::S_AIX_TLSLE, "le"},
52     {PPC::S_AIX_TLSML, "ml"},
53     {PPC::S_DTPMOD, "dtpmod"},
54     {PPC::S_DTPREL_HA, "dtprel@ha"},
55     {PPC::S_DTPREL_HI, "dtprel@h"},
56     {PPC::S_DTPREL_HIGH, "dtprel@high"},
57     {PPC::S_DTPREL_HIGHA, "dtprel@higha"},
58     {PPC::S_DTPREL_HIGHER, "dtprel@higher"},
59     {PPC::S_DTPREL_HIGHERA, "dtprel@highera"},
60     {PPC::S_DTPREL_HIGHEST, "dtprel@highest"},
61     {PPC::S_DTPREL_HIGHESTA, "dtprel@highesta"},
62     {PPC::S_DTPREL_LO, "dtprel@l"},
63     {PPC::S_GOT_DTPREL, "got@dtprel"},
64     {PPC::S_GOT_DTPREL_HA, "got@dtprel@ha"},
65     {PPC::S_GOT_DTPREL_HI, "got@dtprel@h"},
66     {PPC::S_GOT_DTPREL_LO, "got@dtprel@l"},
67     {PPC::S_GOT_PCREL, "got@pcrel"},
68     {PPC::S_GOT_TLSGD, "got@tlsgd"},
69     {PPC::S_GOT_TLSGD_HA, "got@tlsgd@ha"},
70     {PPC::S_GOT_TLSGD_HI, "got@tlsgd@h"},
71     {PPC::S_GOT_TLSGD_LO, "got@tlsgd@l"},
72     {PPC::S_GOT_TLSGD_PCREL, "got@tlsgd@pcrel"},
73     {PPC::S_GOT_TLSLD, "got@tlsld"},
74     {PPC::S_GOT_TLSLD_HA, "got@tlsld@ha"},
75     {PPC::S_GOT_TLSLD_HI, "got@tlsld@h"},
76     {PPC::S_GOT_TLSLD_LO, "got@tlsld@l"},
77     {PPC::S_GOT_TLSLD_PCREL, "got@tlsld@pcrel"},
78     {PPC::S_GOT_TPREL, "got@tprel"},
79     {PPC::S_GOT_TPREL_HA, "got@tprel@ha"},
80     {PPC::S_GOT_TPREL_HI, "got@tprel@h"},
81     {PPC::S_GOT_TPREL_LO, "got@tprel@l"},
82     {PPC::S_GOT_TPREL_PCREL, "got@tprel@pcrel"},
83     {PPC::S_LOCAL, "local"},
84     {PPC::S_NOTOC, "notoc"},
85     {PPC::S_PCREL_OPT, "<<invalid>>"},
86     {PPC::S_TLS, "tls"},
87     {PPC::S_TLS_PCREL, "tls@pcrel"},
88     {PPC::S_TPREL_HA, "tprel@ha"},
89     {PPC::S_TPREL_HI, "tprel@h"},
90     {PPC::S_TPREL_HIGH, "tprel@high"},
91     {PPC::S_TPREL_HIGHA, "tprel@higha"},
92     {PPC::S_TPREL_HIGHER, "tprel@higher"},
93     {PPC::S_TPREL_HIGHERA, "tprel@highera"},
94     {PPC::S_TPREL_HIGHEST, "tprel@highest"},
95     {PPC::S_TPREL_HIGHESTA, "tprel@highesta"},
96     {PPC::S_TPREL_LO, "tprel@l"},
97 };
98 
99 const MCAsmInfo::AtSpecifier xcoffAtSpecifiers[] = {
100     // clang-format off
101     {PPC::S_AIX_TLSGD, "gd"},
102     {PPC::S_AIX_TLSGDM, "m"},
103     {PPC::S_AIX_TLSIE, "ie"},
104     {PPC::S_AIX_TLSLD, "ld"},
105     {PPC::S_AIX_TLSLE, "le"},
106     {PPC::S_AIX_TLSML, "ml"},
107     {PPC::S_L, "l"},
108     {PPC::S_U, "u"},
109     // clang-format on
110 };
111 
evaluateAsInt64(uint16_t specifier,int64_t Value)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 
evaluateAsConstant(const MCSpecifierExpr & Expr,int64_t & Res)138 bool PPC::evaluateAsConstant(const MCSpecifierExpr &Expr, int64_t &Res) {
139   MCValue Value;
140 
141   if (!Expr.getSubExpr()->evaluateAsRelocatable(Value, nullptr))
142     return false;
143 
144   if (!Value.isAbsolute())
145     return false;
146   auto Tmp = evaluateAsInt64(Expr.getSpecifier(), Value.getConstant());
147   if (!Tmp)
148     return false;
149   Res = *Tmp;
150   return true;
151 }
152 
evaluateAsRelocatable(const MCSpecifierExpr & Expr,MCValue & Res,const MCAssembler * Asm)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(Expr.getSpecifier(), Res.getConstant());
163   if (Res.isAbsolute() && MaybeInt) {
164     Res = MCValue::get(*MaybeInt);
165   } else {
166     Res.setSpecifier(Expr.getSpecifier());
167   }
168 
169   return true;
170 }
171 
PPCELFMCAsmInfo(bool is64Bit,const Triple & T)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   AllowDollarAtStartOfIdentifier = false;
196 
197   // Set up DWARF directives
198   MinInstAlignment = 4;
199 
200   // Exceptions handling
201   ExceptionsType = ExceptionHandling::DwarfCFI;
202 
203   ZeroDirective = "\t.space\t";
204   Data64bitsDirective = is64Bit ? "\t.quad\t" : nullptr;
205   AssemblerDialect = 1;           // New-Style mnemonics.
206   LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
207 
208   initializeAtSpecifiers(elfAtSpecifiers);
209 }
210 
printSpecifierExpr(raw_ostream & OS,const MCSpecifierExpr & Expr) const211 void PPCELFMCAsmInfo::printSpecifierExpr(raw_ostream &OS,
212                                          const MCSpecifierExpr &Expr) const {
213   printExpr(OS, *Expr.getSubExpr());
214   OS << '@' << getSpecifierName(Expr.getSpecifier());
215 }
216 
evaluateAsRelocatableImpl(const MCSpecifierExpr & Expr,MCValue & Res,const MCAssembler * Asm) const217 bool PPCELFMCAsmInfo::evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr,
218                                                 MCValue &Res,
219                                                 const MCAssembler *Asm) const {
220   return evaluateAsRelocatable(Expr, Res, Asm);
221 }
222 
anchor()223 void PPCXCOFFMCAsmInfo::anchor() {}
224 
PPCXCOFFMCAsmInfo(bool Is64Bit,const Triple & T)225 PPCXCOFFMCAsmInfo::PPCXCOFFMCAsmInfo(bool Is64Bit, const Triple &T) {
226   if (T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle)
227     report_fatal_error("XCOFF is not supported for little-endian targets");
228   CodePointerSize = CalleeSaveStackSlotSize = Is64Bit ? 8 : 4;
229 
230   // A size of 8 is only supported by the assembler under 64-bit.
231   Data64bitsDirective = Is64Bit ? "\t.vbyte\t8, " : nullptr;
232 
233   // Debug Information
234   SupportsDebugInformation = true;
235 
236   // Set up DWARF directives
237   MinInstAlignment = 4;
238 
239   // Support $ as PC in inline asm
240   DollarIsPC = true;
241   AllowDollarAtStartOfIdentifier = false;
242 
243   UsesSetToEquateSymbol = true;
244 
245   initializeAtSpecifiers(xcoffAtSpecifiers);
246 }
247 
printSpecifierExpr(raw_ostream & OS,const MCSpecifierExpr & Expr) const248 void PPCXCOFFMCAsmInfo::printSpecifierExpr(raw_ostream &OS,
249                                            const MCSpecifierExpr &Expr) const {
250   printExpr(OS, *Expr.getSubExpr());
251   OS << '@' << getSpecifierName(Expr.getSpecifier());
252 }
253 
evaluateAsRelocatableImpl(const MCSpecifierExpr & Expr,MCValue & Res,const MCAssembler * Asm) const254 bool PPCXCOFFMCAsmInfo::evaluateAsRelocatableImpl(
255     const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const {
256   return evaluateAsRelocatable(Expr, Res, Asm);
257 }
258