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
23namespace llvm {
24class MCStreamer;
25class MCValue;
26class Triple;
27
28struct 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
39struct 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
47struct 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
55struct 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
63namespace AArch64 {
64using Specifier = uint16_t;
65
66enum {
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:").
184StringRef getSpecifierName(const MCSpecifierExpr &Expr);
185
186inline Specifier getSymbolLoc(Specifier S) {
187 return static_cast<Specifier>(S & AArch64::S_SymLocBits);
188}
189
190inline Specifier getAddressFrag(Specifier S) {
191 return static_cast<Specifier>(S & AArch64::S_AddressFragBits);
192}
193
194inline bool isNotChecked(Specifier S) { return S & AArch64::S_NC; }
195} // namespace AArch64
196
197class AArch64AuthMCExpr final : public MCSpecifierExpr {
198 uint16_t Discriminator;
199 AArch64PACKey::ID Key;
200
201 explicit AArch64AuthMCExpr(const MCExpr *Expr, uint16_t Discriminator,
202 AArch64PACKey::ID Key, bool HasAddressDiversity)
203 : MCSpecifierExpr(Expr, HasAddressDiversity ? AArch64::S_AUTHADDR
204 : AArch64::S_AUTH),
205 Discriminator(Discriminator), Key(Key) {}
206
207public:
208 static const AArch64AuthMCExpr *
209 create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key,
210 bool HasAddressDiversity, MCContext &Ctx);
211
212 AArch64PACKey::ID getKey() const { return Key; }
213 uint16_t getDiscriminator() const { return Discriminator; }
214 bool hasAddressDiversity() const {
215 return getSpecifier() == AArch64::S_AUTHADDR;
216 }
217
218 void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
219
220 static bool classof(const MCExpr *E) {
221 auto *SE = dyn_cast<MCSpecifierExpr>(Val: E);
222 return SE && (SE->getSpecifier() == AArch64::S_AUTH ||
223 SE->getSpecifier() == AArch64::S_AUTHADDR);
224 }
225};
226
227} // namespace llvm
228
229#endif
230