xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //=====-- AArch64MCAsmInfo.h - AArch64 asm properties ---------*- C++ -*--====//
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 declaration of the AArch64MCAsmInfo class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCASMINFO_H
14 #define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCASMINFO_H
15 
16 #include "Utils/AArch64BaseInfo.h"
17 #include "llvm/MC/MCAsmInfoCOFF.h"
18 #include "llvm/MC/MCAsmInfoDarwin.h"
19 #include "llvm/MC/MCAsmInfoELF.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/Support/Casting.h"
22 
23 namespace llvm {
24 class MCStreamer;
25 class MCValue;
26 class Triple;
27 
28 struct AArch64MCAsmInfoDarwin : public MCAsmInfoDarwin {
29   explicit AArch64MCAsmInfoDarwin(bool IsILP32);
30   const MCExpr *
31   getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding,
32                               MCStreamer &Streamer) const override;
33   void printSpecifierExpr(raw_ostream &OS,
34                           const MCSpecifierExpr &Expr) const override;
35   bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res,
36                                  const MCAssembler *Asm) const override;
37 };
38 
39 struct AArch64MCAsmInfoELF : public MCAsmInfoELF {
40   explicit AArch64MCAsmInfoELF(const Triple &T);
41   void printSpecifierExpr(raw_ostream &OS,
42                           const MCSpecifierExpr &Expr) const override;
43   bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res,
44                                  const MCAssembler *Asm) const override;
45 };
46 
47 struct AArch64MCAsmInfoMicrosoftCOFF : public MCAsmInfoMicrosoft {
48   explicit AArch64MCAsmInfoMicrosoftCOFF();
49   void printSpecifierExpr(raw_ostream &OS,
50                           const MCSpecifierExpr &Expr) const override;
51   bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res,
52                                  const MCAssembler *Asm) const override;
53 };
54 
55 struct AArch64MCAsmInfoGNUCOFF : public MCAsmInfoGNUCOFF {
56   explicit AArch64MCAsmInfoGNUCOFF();
57   void printSpecifierExpr(raw_ostream &OS,
58                           const MCSpecifierExpr &Expr) const override;
59   bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res,
60                                  const MCAssembler *Asm) const override;
61 };
62 
63 namespace AArch64 {
64 using Specifier = uint16_t;
65 
66 enum {
67   // clang-format off
68   S_None         = 0,
69   // Symbol locations specifying (roughly speaking) what calculation should be
70   // performed to construct the final address for the relocated
71   // symbol. E.g. direct, via the GOT, ...
72   S_ABS          = 0x001,
73   S_SABS         = 0x002,
74   S_PREL         = 0x003,
75   S_GOT          = 0x004,
76   S_DTPREL       = 0x005,
77   S_GOTTPREL     = 0x006,
78   S_TPREL        = 0x007,
79   S_TLSDESC      = 0x008,
80   S_SECREL       = 0x009,
81   S_AUTH         = 0x00a,
82   S_AUTHADDR     = 0x00b,
83   S_GOT_AUTH     = 0x00c,
84   S_TLSDESC_AUTH = 0x00d,
85   S_SymLocBits   = 0x00f,
86 
87   // Variants specifying which part of the final address calculation is
88   // used. E.g. the low 12 bits for an ADD/LDR, the middle 16 bits for a
89   // MOVZ/MOVK.
90   S_PAGE         = 0x010,
91   S_PAGEOFF      = 0x020,
92   S_HI12         = 0x030,
93   S_G0           = 0x040,
94   S_G1           = 0x050,
95   S_G2           = 0x060,
96   S_G3           = 0x070,
97   S_LO15         = 0x080,
98   S_AddressFragBits = 0x0f0,
99 
100   // Whether the final relocation is a checked one (where a linker should
101   // perform a range-check on the final address) or not. Note that this field
102   // is unfortunately sometimes omitted from the assembly syntax. E.g. :lo12:
103   // on its own is a non-checked relocation. We side with ELF on being
104   // explicit about this!
105   S_NC           = 0x100,
106 
107   // Convenience definitions for referring to specific textual representations
108   // of relocation specifiers. Note that this means the "_NC" is sometimes
109   // omitted in line with assembly syntax here (S_LO12 rather than VK_LO12_NC
110   // since a user would write ":lo12:").
111   S_CALL              = S_ABS,
112   S_ABS_PAGE          = S_ABS          | S_PAGE,
113   S_ABS_PAGE_NC       = S_ABS          | S_PAGE    | S_NC,
114   S_ABS_G3            = S_ABS          | S_G3,
115   S_ABS_G2            = S_ABS          | S_G2,
116   S_ABS_G2_S          = S_SABS         | S_G2,
117   S_ABS_G2_NC         = S_ABS          | S_G2      | S_NC,
118   S_ABS_G1            = S_ABS          | S_G1,
119   S_ABS_G1_S          = S_SABS         | S_G1,
120   S_ABS_G1_NC         = S_ABS          | S_G1      | S_NC,
121   S_ABS_G0            = S_ABS          | S_G0,
122   S_ABS_G0_S          = S_SABS         | S_G0,
123   S_ABS_G0_NC         = S_ABS          | S_G0      | S_NC,
124   S_LO12              = S_ABS          | S_PAGEOFF | S_NC,
125   S_PREL_G3           = S_PREL         | S_G3,
126   S_PREL_G2           = S_PREL         | S_G2,
127   S_PREL_G2_NC        = S_PREL         | S_G2      | S_NC,
128   S_PREL_G1           = S_PREL         | S_G1,
129   S_PREL_G1_NC        = S_PREL         | S_G1      | S_NC,
130   S_PREL_G0           = S_PREL         | S_G0,
131   S_PREL_G0_NC        = S_PREL         | S_G0      | S_NC,
132   S_GOT_LO12          = S_GOT          | S_PAGEOFF | S_NC,
133   S_GOT_PAGE          = S_GOT          | S_PAGE,
134   S_GOT_PAGE_LO15     = S_GOT          | S_LO15    | S_NC,
135   S_GOT_AUTH_LO12     = S_GOT_AUTH     | S_PAGEOFF | S_NC,
136   S_GOT_AUTH_PAGE     = S_GOT_AUTH     | S_PAGE,
137   S_DTPREL_G2         = S_DTPREL       | S_G2,
138   S_DTPREL_G1         = S_DTPREL       | S_G1,
139   S_DTPREL_G1_NC      = S_DTPREL       | S_G1      | S_NC,
140   S_DTPREL_G0         = S_DTPREL       | S_G0,
141   S_DTPREL_G0_NC      = S_DTPREL       | S_G0      | S_NC,
142   S_DTPREL_HI12       = S_DTPREL       | S_HI12,
143   S_DTPREL_LO12       = S_DTPREL       | S_PAGEOFF,
144   S_DTPREL_LO12_NC    = S_DTPREL       | S_PAGEOFF | S_NC,
145   S_GOTTPREL_PAGE     = S_GOTTPREL     | S_PAGE,
146   S_GOTTPREL_LO12_NC  = S_GOTTPREL     | S_PAGEOFF | S_NC,
147   S_GOTTPREL_G1       = S_GOTTPREL     | S_G1,
148   S_GOTTPREL_G0_NC    = S_GOTTPREL     | S_G0      | S_NC,
149   S_TPREL_G2          = S_TPREL        | S_G2,
150   S_TPREL_G1          = S_TPREL        | S_G1,
151   S_TPREL_G1_NC       = S_TPREL        | S_G1      | S_NC,
152   S_TPREL_G0          = S_TPREL        | S_G0,
153   S_TPREL_G0_NC       = S_TPREL        | S_G0      | S_NC,
154   S_TPREL_HI12        = S_TPREL        | S_HI12,
155   S_TPREL_LO12        = S_TPREL        | S_PAGEOFF,
156   S_TPREL_LO12_NC     = S_TPREL        | S_PAGEOFF | S_NC,
157   S_TLSDESC_LO12      = S_TLSDESC      | S_PAGEOFF,
158   S_TLSDESC_PAGE      = S_TLSDESC      | S_PAGE,
159   S_TLSDESC_AUTH_LO12 = S_TLSDESC_AUTH | S_PAGEOFF,
160   S_TLSDESC_AUTH_PAGE = S_TLSDESC_AUTH | S_PAGE,
161   S_SECREL_LO12       = S_SECREL       | S_PAGEOFF,
162   S_SECREL_HI12       = S_SECREL       | S_HI12,
163 
164   // ELF relocation specifiers in data directives:
165   S_PLT          = 0x400,
166   S_GOTPCREL,
167 
168   // Mach-O @ relocation specifiers:
169   S_MACHO_GOT,
170   S_MACHO_GOTPAGE,
171   S_MACHO_GOTPAGEOFF,
172   S_MACHO_PAGE,
173   S_MACHO_PAGEOFF,
174   S_MACHO_TLVP,
175   S_MACHO_TLVPPAGE,
176   S_MACHO_TLVPPAGEOFF,
177 
178   S_INVALID  = 0xfff
179   // clang-format on
180 };
181 
182 /// Return the string representation of the ELF relocation specifier
183 /// (e.g. ":got:", ":lo12:").
184 StringRef getSpecifierName(const MCSpecifierExpr &Expr);
185 
getSymbolLoc(Specifier S)186 inline Specifier getSymbolLoc(Specifier S) {
187   return static_cast<Specifier>(S & AArch64::S_SymLocBits);
188 }
189 
getAddressFrag(Specifier S)190 inline Specifier getAddressFrag(Specifier S) {
191   return static_cast<Specifier>(S & AArch64::S_AddressFragBits);
192 }
193 
isNotChecked(Specifier S)194 inline bool isNotChecked(Specifier S) { return S & AArch64::S_NC; }
195 } // namespace AArch64
196 
197 class AArch64AuthMCExpr final : public MCSpecifierExpr {
198   uint16_t Discriminator;
199   AArch64PACKey::ID Key;
200 
AArch64AuthMCExpr(const MCExpr * Expr,uint16_t Discriminator,AArch64PACKey::ID Key,bool HasAddressDiversity,SMLoc Loc)201   explicit AArch64AuthMCExpr(const MCExpr *Expr, uint16_t Discriminator,
202                              AArch64PACKey::ID Key, bool HasAddressDiversity,
203                              SMLoc Loc)
204       : MCSpecifierExpr(
205             Expr, HasAddressDiversity ? AArch64::S_AUTHADDR : AArch64::S_AUTH,
206             Loc),
207         Discriminator(Discriminator), Key(Key) {}
208 
209 public:
210   static const AArch64AuthMCExpr *
211   create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key,
212          bool HasAddressDiversity, MCContext &Ctx, SMLoc Loc = SMLoc());
213 
getKey()214   AArch64PACKey::ID getKey() const { return Key; }
getDiscriminator()215   uint16_t getDiscriminator() const { return Discriminator; }
hasAddressDiversity()216   bool hasAddressDiversity() const {
217     return getSpecifier() == AArch64::S_AUTHADDR;
218   }
219 
220   void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
221 
classof(const MCExpr * E)222   static bool classof(const MCExpr *E) {
223     auto *SE = dyn_cast<MCSpecifierExpr>(E);
224     return SE && (SE->getSpecifier() == AArch64::S_AUTH ||
225                   SE->getSpecifier() == AArch64::S_AUTHADDR);
226   }
227 };
228 
229 } // namespace llvm
230 
231 #endif
232